wangxx před 5 měsíci
rodič
revize
91f8d0ade7
100 změnil soubory, kde provedl 13347 přidání a 0 odebrání
  1. 89 0
      airport-framework/pom.xml
  2. 184 0
      airport-framework/src/main/java/com/sundot/airport/framework/aspectj/DataScopeAspect.java
  3. 72 0
      airport-framework/src/main/java/com/sundot/airport/framework/aspectj/DataSourceAspect.java
  4. 256 0
      airport-framework/src/main/java/com/sundot/airport/framework/aspectj/LogAspect.java
  5. 89 0
      airport-framework/src/main/java/com/sundot/airport/framework/aspectj/RateLimiterAspect.java
  6. 30 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/ApplicationConfig.java
  7. 83 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/CaptchaConfig.java
  8. 126 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/DruidConfig.java
  9. 52 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/FastJson2JsonRedisSerializer.java
  10. 58 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/FilterConfig.java
  11. 43 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/I18nConfig.java
  12. 68 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/KaptchaTextCreator.java
  13. 132 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/MyBatisConfig.java
  14. 57 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/MybatisPlusConfig.java
  15. 69 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/RedisConfig.java
  16. 72 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/ResourcesConfig.java
  17. 139 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/SecurityConfig.java
  18. 48 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/ServerConfig.java
  19. 63 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/ThreadPoolConfig.java
  20. 27 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/WebAdminInterceptorConfig.java
  21. 89 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/properties/DruidProperties.java
  22. 73 0
      airport-framework/src/main/java/com/sundot/airport/framework/config/properties/PermitAllUrlProperties.java
  23. 26 0
      airport-framework/src/main/java/com/sundot/airport/framework/datasource/DynamicDataSource.java
  24. 45 0
      airport-framework/src/main/java/com/sundot/airport/framework/datasource/DynamicDataSourceContextHolder.java
  25. 56 0
      airport-framework/src/main/java/com/sundot/airport/framework/interceptor/RepeatSubmitInterceptor.java
  26. 70 0
      airport-framework/src/main/java/com/sundot/airport/framework/interceptor/RequestSourceInterceptor.java
  27. 110 0
      airport-framework/src/main/java/com/sundot/airport/framework/interceptor/impl/SameUrlDataInterceptor.java
  28. 55 0
      airport-framework/src/main/java/com/sundot/airport/framework/manager/AsyncManager.java
  29. 39 0
      airport-framework/src/main/java/com/sundot/airport/framework/manager/ShutdownManager.java
  30. 102 0
      airport-framework/src/main/java/com/sundot/airport/framework/manager/factory/AsyncFactory.java
  31. 28 0
      airport-framework/src/main/java/com/sundot/airport/framework/security/context/AuthenticationContextHolder.java
  32. 27 0
      airport-framework/src/main/java/com/sundot/airport/framework/security/context/PermissionContextHolder.java
  33. 44 0
      airport-framework/src/main/java/com/sundot/airport/framework/security/filter/JwtAuthenticationTokenFilter.java
  34. 34 0
      airport-framework/src/main/java/com/sundot/airport/framework/security/handle/AuthenticationEntryPointImpl.java
  35. 53 0
      airport-framework/src/main/java/com/sundot/airport/framework/security/handle/LogoutSuccessHandlerImpl.java
  36. 240 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/domain/Server.java
  37. 101 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Cpu.java
  38. 130 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Jvm.java
  39. 61 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Mem.java
  40. 84 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Sys.java
  41. 114 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/SysFile.java
  42. 164 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/exception/GlobalExceptionHandler.java
  43. 159 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/PermissionService.java
  44. 181 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysLoginService.java
  45. 86 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysPasswordService.java
  46. 88 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysPermissionService.java
  47. 117 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysRegisterService.java
  48. 232 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/TokenService.java
  49. 66 0
      airport-framework/src/main/java/com/sundot/airport/framework/web/service/UserDetailsServiceImpl.java
  50. 40 0
      airport-generator/pom.xml
  51. 87 0
      airport-generator/src/main/java/com/sundot/airport/generator/config/GenConfig.java
  52. 263 0
      airport-generator/src/main/java/com/sundot/airport/generator/controller/GenController.java
  53. 385 0
      airport-generator/src/main/java/com/sundot/airport/generator/domain/GenTable.java
  54. 373 0
      airport-generator/src/main/java/com/sundot/airport/generator/domain/GenTableColumn.java
  55. 60 0
      airport-generator/src/main/java/com/sundot/airport/generator/mapper/GenTableColumnMapper.java
  56. 91 0
      airport-generator/src/main/java/com/sundot/airport/generator/mapper/GenTableMapper.java
  57. 68 0
      airport-generator/src/main/java/com/sundot/airport/generator/service/GenTableColumnServiceImpl.java
  58. 531 0
      airport-generator/src/main/java/com/sundot/airport/generator/service/GenTableServiceImpl.java
  59. 44 0
      airport-generator/src/main/java/com/sundot/airport/generator/service/IGenTableColumnService.java
  60. 130 0
      airport-generator/src/main/java/com/sundot/airport/generator/service/IGenTableService.java
  61. 257 0
      airport-generator/src/main/java/com/sundot/airport/generator/util/GenUtils.java
  62. 34 0
      airport-generator/src/main/java/com/sundot/airport/generator/util/VelocityInitializer.java
  63. 408 0
      airport-generator/src/main/java/com/sundot/airport/generator/util/VelocityUtils.java
  64. 12 0
      airport-generator/src/main/resources/generator.yml
  65. 127 0
      airport-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
  66. 210 0
      airport-generator/src/main/resources/mapper/generator/GenTableMapper.xml
  67. 115 0
      airport-generator/src/main/resources/vm/java/controller.java.vm
  68. 105 0
      airport-generator/src/main/resources/vm/java/domain.java.vm
  69. 91 0
      airport-generator/src/main/resources/vm/java/mapper.java.vm
  70. 61 0
      airport-generator/src/main/resources/vm/java/service.java.vm
  71. 169 0
      airport-generator/src/main/resources/vm/java/serviceImpl.java.vm
  72. 76 0
      airport-generator/src/main/resources/vm/java/sub-domain.java.vm
  73. 44 0
      airport-generator/src/main/resources/vm/js/api.js.vm
  74. 22 0
      airport-generator/src/main/resources/vm/sql/sql.vm
  75. 505 0
      airport-generator/src/main/resources/vm/vue/index-tree.vue.vm
  76. 602 0
      airport-generator/src/main/resources/vm/vue/index.vue.vm
  77. 474 0
      airport-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
  78. 590 0
      airport-generator/src/main/resources/vm/vue/v3/index.vue.vm
  79. 140 0
      airport-generator/src/main/resources/vm/xml/mapper.xml.vm
  80. 37 0
      airport-item/pom.xml
  81. 50 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenChannelDto.java
  82. 60 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenCommonDto.java
  83. 36 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenDailyTrendDto.java
  84. 208 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenInfoDto.java
  85. 28 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenPositionAppDto.java
  86. 50 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenPositionDto.java
  87. 53 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenStatsDto.java
  88. 32 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenTimeSpanDto.java
  89. 56 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenTotalSomeDto.java
  90. 71 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureCount.java
  91. 786 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureDto.java
  92. 435 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureItems.java
  93. 151 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureParam.java
  94. 538 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureRecord.java
  95. 24 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureRecordDTO.java
  96. 59 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureTotal.java
  97. 29 0
      airport-item/src/main/java/com/sundot/airport/item/domain/portrait/ItemSeizureModuleIndicatorResult.java
  98. 16 0
      airport-item/src/main/java/com/sundot/airport/item/domain/portrait/SeizureStats.java
  99. 83 0
      airport-item/src/main/java/com/sundot/airport/item/domain/vo/ItemSeizureRecordExportVO.java
  100. 0 0
      airport-item/src/main/java/com/sundot/airport/item/mapper/ItemLargeScreenMapper.java

+ 89 - 0
airport-framework/pom.xml

@@ -0,0 +1,89 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <parent>
6
+        <artifactId>airport</artifactId>
7
+        <groupId>com.sundot.airport</groupId>
8
+        <version>3.9.0</version>
9
+    </parent>
10
+    <modelVersion>4.0.0</modelVersion>
11
+
12
+    <artifactId>airport-framework</artifactId>
13
+
14
+    <description>
15
+        framework框架核心
16
+    </description>
17
+
18
+    <dependencies>
19
+
20
+        <!-- SpringBoot Web容器 -->
21
+         <dependency>
22
+            <groupId>org.springframework.boot</groupId>
23
+            <artifactId>spring-boot-starter-web</artifactId>
24
+            <exclusions>
25
+                <!-- 排除默认的 Tomcat -->
26
+                <exclusion>
27
+                    <groupId>org.springframework.boot</groupId>
28
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
29
+                </exclusion>
30
+            </exclusions>
31
+        </dependency>
32
+
33
+        <!-- 使用 Undertow 替代 Tomcat -->
34
+        <dependency>
35
+            <groupId>org.springframework.boot</groupId>
36
+            <artifactId>spring-boot-starter-undertow</artifactId>
37
+        </dependency>
38
+
39
+        <!-- SpringBoot 拦截器 -->
40
+        <dependency>
41
+            <groupId>org.springframework.boot</groupId>
42
+            <artifactId>spring-boot-starter-aop</artifactId>
43
+        </dependency>
44
+
45
+        <!-- 阿里数据库连接池 -->
46
+        <dependency>
47
+            <groupId>com.alibaba</groupId>
48
+            <artifactId>druid-spring-boot-starter</artifactId>
49
+        </dependency>
50
+
51
+        <!-- 验证码 -->
52
+        <dependency>
53
+            <groupId>pro.fessional</groupId>
54
+            <artifactId>kaptcha</artifactId>
55
+            <exclusions>
56
+                <exclusion>
57
+                    <artifactId>servlet-api</artifactId>
58
+                    <groupId>javax.servlet</groupId>
59
+                </exclusion>
60
+            </exclusions>
61
+        </dependency>
62
+
63
+        <!-- 获取系统信息 -->
64
+        <dependency>
65
+            <groupId>com.github.oshi</groupId>
66
+            <artifactId>oshi-core</artifactId>
67
+        </dependency>
68
+
69
+        <!-- 系统模块-->
70
+        <dependency>
71
+            <groupId>com.sundot.airport</groupId>
72
+            <artifactId>airport-system</artifactId>
73
+        </dependency>
74
+
75
+        <!-- 考试模块-->
76
+        <dependency>
77
+            <groupId>com.sundot.airport</groupId>
78
+            <artifactId>airport-exam</artifactId>
79
+        </dependency>
80
+
81
+        <!-- 考勤模块-->
82
+        <dependency>
83
+            <groupId>com.sundot.airport</groupId>
84
+            <artifactId>airport-attendance</artifactId>
85
+        </dependency>
86
+
87
+    </dependencies>
88
+
89
+</project>

+ 184 - 0
airport-framework/src/main/java/com/sundot/airport/framework/aspectj/DataScopeAspect.java

@@ -0,0 +1,184 @@
1
+package com.sundot.airport.framework.aspectj;
2
+
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+import org.aspectj.lang.JoinPoint;
6
+import org.aspectj.lang.annotation.Aspect;
7
+import org.aspectj.lang.annotation.Before;
8
+import org.springframework.stereotype.Component;
9
+import com.sundot.airport.common.annotation.DataScope;
10
+import com.sundot.airport.common.constant.UserConstants;
11
+import com.sundot.airport.common.core.domain.BaseEntity;
12
+import com.sundot.airport.common.core.domain.entity.SysRole;
13
+import com.sundot.airport.common.core.domain.entity.SysUser;
14
+import com.sundot.airport.common.core.domain.model.LoginUser;
15
+import com.sundot.airport.common.core.text.Convert;
16
+import com.sundot.airport.common.utils.SecurityUtils;
17
+import com.sundot.airport.common.utils.StringUtils;
18
+import com.sundot.airport.framework.security.context.PermissionContextHolder;
19
+
20
+/**
21
+ * 数据过滤处理
22
+ *
23
+ * @author ruoyi
24
+ */
25
+@Aspect
26
+@Component
27
+public class DataScopeAspect
28
+{
29
+    /**
30
+     * 全部数据权限
31
+     */
32
+    public static final String DATA_SCOPE_ALL = "1";
33
+
34
+    /**
35
+     * 自定数据权限
36
+     */
37
+    public static final String DATA_SCOPE_CUSTOM = "2";
38
+
39
+    /**
40
+     * 部门数据权限
41
+     */
42
+    public static final String DATA_SCOPE_DEPT = "3";
43
+
44
+    /**
45
+     * 部门及以下数据权限
46
+     */
47
+    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
48
+
49
+    /**
50
+     * 仅本人数据权限
51
+     */
52
+    public static final String DATA_SCOPE_SELF = "5";
53
+
54
+    /**
55
+     * 数据权限过滤关键字
56
+     */
57
+    public static final String DATA_SCOPE = "dataScope";
58
+
59
+    @Before("@annotation(controllerDataScope)")
60
+    public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
61
+    {
62
+        clearDataScope(point);
63
+        handleDataScope(point, controllerDataScope);
64
+    }
65
+
66
+    protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
67
+    {
68
+        // 获取当前的用户
69
+        LoginUser loginUser = SecurityUtils.getLoginUser();
70
+        if (StringUtils.isNotNull(loginUser))
71
+        {
72
+            SysUser currentUser = loginUser.getUser();
73
+            // 如果是超级管理员,则不过滤数据
74
+            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
75
+            {
76
+                String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
77
+                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
78
+            }
79
+        }
80
+    }
81
+
82
+    /**
83
+     * 数据范围过滤
84
+     *
85
+     * @param joinPoint 切点
86
+     * @param user 用户
87
+     * @param deptAlias 部门别名
88
+     * @param userAlias 用户别名
89
+     * @param permission 权限字符
90
+     */
91
+    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
92
+    {
93
+        StringBuilder sqlString = new StringBuilder();
94
+        List<String> conditions = new ArrayList<String>();
95
+        List<String> scopeCustomIds = new ArrayList<String>();
96
+        user.getRoles().forEach(role -> {
97
+            if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
98
+            {
99
+                scopeCustomIds.add(Convert.toStr(role.getRoleId()));
100
+            }
101
+        });
102
+
103
+        for (SysRole role : user.getRoles())
104
+        {
105
+            String dataScope = role.getDataScope();
106
+            if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
107
+            {
108
+                continue;
109
+            }
110
+            if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
111
+            {
112
+                continue;
113
+            }
114
+            if (DATA_SCOPE_ALL.equals(dataScope))
115
+            {
116
+                sqlString = new StringBuilder();
117
+                conditions.add(dataScope);
118
+                break;
119
+            }
120
+            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
121
+            {
122
+                if (scopeCustomIds.size() > 1)
123
+                {
124
+                    // 多个自定数据权限使用in查询,避免多次拼接。
125
+                    sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
126
+                }
127
+                else
128
+                {
129
+                    sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
130
+                }
131
+            }
132
+            else if (DATA_SCOPE_DEPT.equals(dataScope))
133
+            {
134
+                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
135
+            }
136
+            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
137
+            {
138
+                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()));
139
+            }
140
+            else if (DATA_SCOPE_SELF.equals(dataScope))
141
+            {
142
+                if (StringUtils.isNotBlank(userAlias))
143
+                {
144
+                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
145
+                }
146
+                else
147
+                {
148
+                    // 数据权限为仅本人且没有userAlias别名不查询任何数据
149
+                    sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
150
+                }
151
+            }
152
+            conditions.add(dataScope);
153
+        }
154
+
155
+        // 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
156
+        if (StringUtils.isEmpty(conditions))
157
+        {
158
+            sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
159
+        }
160
+
161
+        if (StringUtils.isNotBlank(sqlString.toString()))
162
+        {
163
+            Object params = joinPoint.getArgs()[0];
164
+            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
165
+            {
166
+                BaseEntity baseEntity = (BaseEntity) params;
167
+                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
168
+            }
169
+        }
170
+    }
171
+
172
+    /**
173
+     * 拼接权限sql前先清空params.dataScope参数防止注入
174
+     */
175
+    private void clearDataScope(final JoinPoint joinPoint)
176
+    {
177
+        Object params = joinPoint.getArgs()[0];
178
+        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
179
+        {
180
+            BaseEntity baseEntity = (BaseEntity) params;
181
+            baseEntity.getParams().put(DATA_SCOPE, "");
182
+        }
183
+    }
184
+}

+ 72 - 0
airport-framework/src/main/java/com/sundot/airport/framework/aspectj/DataSourceAspect.java

@@ -0,0 +1,72 @@
1
+package com.sundot.airport.framework.aspectj;
2
+
3
+import java.util.Objects;
4
+import org.aspectj.lang.ProceedingJoinPoint;
5
+import org.aspectj.lang.annotation.Around;
6
+import org.aspectj.lang.annotation.Aspect;
7
+import org.aspectj.lang.annotation.Pointcut;
8
+import org.aspectj.lang.reflect.MethodSignature;
9
+import org.slf4j.Logger;
10
+import org.slf4j.LoggerFactory;
11
+import org.springframework.core.annotation.AnnotationUtils;
12
+import org.springframework.core.annotation.Order;
13
+import org.springframework.stereotype.Component;
14
+import com.sundot.airport.common.annotation.DataSource;
15
+import com.sundot.airport.common.utils.StringUtils;
16
+import com.sundot.airport.framework.datasource.DynamicDataSourceContextHolder;
17
+
18
+/**
19
+ * 多数据源处理
20
+ * 
21
+ * @author ruoyi
22
+ */
23
+@Aspect
24
+@Order(1)
25
+@Component
26
+public class DataSourceAspect
27
+{
28
+    protected Logger logger = LoggerFactory.getLogger(getClass());
29
+
30
+    @Pointcut("@annotation(com.sundot.airport.common.annotation.DataSource)"
31
+            + "|| @within(com.sundot.airport.common.annotation.DataSource)")
32
+    public void dsPointCut()
33
+    {
34
+
35
+    }
36
+
37
+    @Around("dsPointCut()")
38
+    public Object around(ProceedingJoinPoint point) throws Throwable
39
+    {
40
+        DataSource dataSource = getDataSource(point);
41
+
42
+        if (StringUtils.isNotNull(dataSource))
43
+        {
44
+            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
45
+        }
46
+
47
+        try
48
+        {
49
+            return point.proceed();
50
+        }
51
+        finally
52
+        {
53
+            // 销毁数据源 在执行方法之后
54
+            DynamicDataSourceContextHolder.clearDataSourceType();
55
+        }
56
+    }
57
+
58
+    /**
59
+     * 获取需要切换的数据源
60
+     */
61
+    public DataSource getDataSource(ProceedingJoinPoint point)
62
+    {
63
+        MethodSignature signature = (MethodSignature) point.getSignature();
64
+        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
65
+        if (Objects.nonNull(dataSource))
66
+        {
67
+            return dataSource;
68
+        }
69
+
70
+        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
71
+    }
72
+}

+ 256 - 0
airport-framework/src/main/java/com/sundot/airport/framework/aspectj/LogAspect.java

@@ -0,0 +1,256 @@
1
+package com.sundot.airport.framework.aspectj;
2
+
3
+import java.util.Collection;
4
+import java.util.Map;
5
+import javax.servlet.http.HttpServletRequest;
6
+import javax.servlet.http.HttpServletResponse;
7
+import org.apache.commons.lang3.ArrayUtils;
8
+import org.aspectj.lang.JoinPoint;
9
+import org.aspectj.lang.annotation.AfterReturning;
10
+import org.aspectj.lang.annotation.AfterThrowing;
11
+import org.aspectj.lang.annotation.Aspect;
12
+import org.aspectj.lang.annotation.Before;
13
+import org.slf4j.Logger;
14
+import org.slf4j.LoggerFactory;
15
+import org.springframework.core.NamedThreadLocal;
16
+import org.springframework.stereotype.Component;
17
+import org.springframework.validation.BindingResult;
18
+import org.springframework.web.multipart.MultipartFile;
19
+import com.alibaba.fastjson2.JSON;
20
+import com.sundot.airport.common.annotation.Log;
21
+import com.sundot.airport.common.core.domain.entity.SysUser;
22
+import com.sundot.airport.common.core.domain.model.LoginUser;
23
+import com.sundot.airport.common.core.text.Convert;
24
+import com.sundot.airport.common.enums.BusinessStatus;
25
+import com.sundot.airport.common.enums.HttpMethod;
26
+import com.sundot.airport.common.filter.PropertyPreExcludeFilter;
27
+import com.sundot.airport.common.utils.ExceptionUtil;
28
+import com.sundot.airport.common.utils.SecurityUtils;
29
+import com.sundot.airport.common.utils.ServletUtils;
30
+import com.sundot.airport.common.utils.StringUtils;
31
+import com.sundot.airport.common.utils.ip.IpUtils;
32
+import com.sundot.airport.framework.manager.AsyncManager;
33
+import com.sundot.airport.framework.manager.factory.AsyncFactory;
34
+import com.sundot.airport.system.domain.SysOperLog;
35
+
36
+/**
37
+ * 操作日志记录处理
38
+ * 
39
+ * @author ruoyi
40
+ */
41
+@Aspect
42
+@Component
43
+public class LogAspect
44
+{
45
+    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
46
+
47
+    /** 排除敏感属性字段 */
48
+    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
49
+
50
+    /** 计算操作消耗时间 */
51
+    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
52
+
53
+    /**
54
+     * 处理请求前执行
55
+     */
56
+    @Before(value = "@annotation(controllerLog)")
57
+    public void doBefore(JoinPoint joinPoint, Log controllerLog)
58
+    {
59
+        TIME_THREADLOCAL.set(System.currentTimeMillis());
60
+    }
61
+
62
+    /**
63
+     * 处理完请求后执行
64
+     *
65
+     * @param joinPoint 切点
66
+     */
67
+    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
68
+    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
69
+    {
70
+        handleLog(joinPoint, controllerLog, null, jsonResult);
71
+    }
72
+
73
+    /**
74
+     * 拦截异常操作
75
+     * 
76
+     * @param joinPoint 切点
77
+     * @param e 异常
78
+     */
79
+    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
80
+    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
81
+    {
82
+        handleLog(joinPoint, controllerLog, e, null);
83
+    }
84
+
85
+    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
86
+    {
87
+        try
88
+        {
89
+            // 获取当前的用户
90
+            LoginUser loginUser = SecurityUtils.getLoginUser();
91
+
92
+            // *========数据库日志=========*//
93
+            SysOperLog operLog = new SysOperLog();
94
+            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
95
+            // 请求的地址
96
+            String ip = IpUtils.getIpAddr();
97
+            operLog.setOperIp(ip);
98
+            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
99
+            if (loginUser != null)
100
+            {
101
+                operLog.setOperName(loginUser.getUsername());
102
+                SysUser currentUser = loginUser.getUser();
103
+                if (StringUtils.isNotNull(currentUser) && StringUtils.isNotNull(currentUser.getDept()))
104
+                {
105
+                    operLog.setDeptName(currentUser.getDept().getDeptName());
106
+                }
107
+            }
108
+
109
+            if (e != null)
110
+            {
111
+                operLog.setStatus(BusinessStatus.FAIL.ordinal());
112
+                operLog.setErrorMsg(StringUtils.substring(Convert.toStr(e.getMessage(), ExceptionUtil.getExceptionMessage(e)), 0, 2000));
113
+            }
114
+            // 设置方法名称
115
+            String className = joinPoint.getTarget().getClass().getName();
116
+            String methodName = joinPoint.getSignature().getName();
117
+            operLog.setMethod(className + "." + methodName + "()");
118
+            // 设置请求方式
119
+            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
120
+            // 处理设置注解上的参数
121
+            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
122
+            // 设置消耗时间
123
+            operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
124
+            // 保存数据库
125
+            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
126
+        }
127
+        catch (Exception exp)
128
+        {
129
+            // 记录本地异常日志
130
+            log.error("异常信息:{}", exp.getMessage());
131
+            exp.printStackTrace();
132
+        }
133
+        finally
134
+        {
135
+            TIME_THREADLOCAL.remove();
136
+        }
137
+    }
138
+
139
+    /**
140
+     * 获取注解中对方法的描述信息 用于Controller层注解
141
+     * 
142
+     * @param log 日志
143
+     * @param operLog 操作日志
144
+     * @throws Exception
145
+     */
146
+    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
147
+    {
148
+        // 设置action动作
149
+        operLog.setBusinessType(log.businessType().ordinal());
150
+        // 设置标题
151
+        operLog.setTitle(log.title());
152
+        // 设置操作人类别
153
+        operLog.setOperatorType(log.operatorType().ordinal());
154
+        // 是否需要保存request,参数和值
155
+        if (log.isSaveRequestData())
156
+        {
157
+            // 获取参数的信息,传入到数据库中。
158
+            setRequestValue(joinPoint, operLog, log.excludeParamNames());
159
+        }
160
+        // 是否需要保存response,参数和值
161
+        if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
162
+        {
163
+            operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 20000));
164
+        }
165
+    }
166
+
167
+    /**
168
+     * 获取请求的参数,放到log中
169
+     * 
170
+     * @param operLog 操作日志
171
+     * @throws Exception 异常
172
+     */
173
+    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
174
+    {
175
+        Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
176
+        String requestMethod = operLog.getRequestMethod();
177
+        if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
178
+        {
179
+            String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
180
+            operLog.setOperParam(StringUtils.substring(params, 0, 20000));
181
+        }
182
+        else
183
+        {
184
+            operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 20000));
185
+        }
186
+    }
187
+
188
+    /**
189
+     * 参数拼装
190
+     */
191
+    private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
192
+    {
193
+        String params = "";
194
+        if (paramsArray != null && paramsArray.length > 0)
195
+        {
196
+            for (Object o : paramsArray)
197
+            {
198
+                if (StringUtils.isNotNull(o) && !isFilterObject(o))
199
+                {
200
+                    try
201
+                    {
202
+                        String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
203
+                        params += jsonObj.toString() + " ";
204
+                    }
205
+                    catch (Exception e)
206
+                    {
207
+                    }
208
+                }
209
+            }
210
+        }
211
+        return params.trim();
212
+    }
213
+
214
+    /**
215
+     * 忽略敏感属性
216
+     */
217
+    public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
218
+    {
219
+        return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
220
+    }
221
+
222
+    /**
223
+     * 判断是否需要过滤的对象。
224
+     * 
225
+     * @param o 对象信息。
226
+     * @return 如果是需要过滤的对象,则返回true;否则返回false。
227
+     */
228
+    @SuppressWarnings("rawtypes")
229
+    public boolean isFilterObject(final Object o)
230
+    {
231
+        Class<?> clazz = o.getClass();
232
+        if (clazz.isArray())
233
+        {
234
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
235
+        }
236
+        else if (Collection.class.isAssignableFrom(clazz))
237
+        {
238
+            Collection collection = (Collection) o;
239
+            for (Object value : collection)
240
+            {
241
+                return value instanceof MultipartFile;
242
+            }
243
+        }
244
+        else if (Map.class.isAssignableFrom(clazz))
245
+        {
246
+            Map map = (Map) o;
247
+            for (Object value : map.entrySet())
248
+            {
249
+                Map.Entry entry = (Map.Entry) value;
250
+                return entry.getValue() instanceof MultipartFile;
251
+            }
252
+        }
253
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
254
+                || o instanceof BindingResult;
255
+    }
256
+}

+ 89 - 0
airport-framework/src/main/java/com/sundot/airport/framework/aspectj/RateLimiterAspect.java

@@ -0,0 +1,89 @@
1
+package com.sundot.airport.framework.aspectj;
2
+
3
+import java.lang.reflect.Method;
4
+import java.util.Collections;
5
+import java.util.List;
6
+import org.aspectj.lang.JoinPoint;
7
+import org.aspectj.lang.annotation.Aspect;
8
+import org.aspectj.lang.annotation.Before;
9
+import org.aspectj.lang.reflect.MethodSignature;
10
+import org.slf4j.Logger;
11
+import org.slf4j.LoggerFactory;
12
+import org.springframework.beans.factory.annotation.Autowired;
13
+import org.springframework.data.redis.core.RedisTemplate;
14
+import org.springframework.data.redis.core.script.RedisScript;
15
+import org.springframework.stereotype.Component;
16
+import com.sundot.airport.common.annotation.RateLimiter;
17
+import com.sundot.airport.common.enums.LimitType;
18
+import com.sundot.airport.common.exception.ServiceException;
19
+import com.sundot.airport.common.utils.StringUtils;
20
+import com.sundot.airport.common.utils.ip.IpUtils;
21
+
22
+/**
23
+ * 限流处理
24
+ *
25
+ * @author ruoyi
26
+ */
27
+@Aspect
28
+@Component
29
+public class RateLimiterAspect
30
+{
31
+    private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
32
+
33
+    private RedisTemplate<Object, Object> redisTemplate;
34
+
35
+    private RedisScript<Long> limitScript;
36
+
37
+    @Autowired
38
+    public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
39
+    {
40
+        this.redisTemplate = redisTemplate;
41
+    }
42
+
43
+    @Autowired
44
+    public void setLimitScript(RedisScript<Long> limitScript)
45
+    {
46
+        this.limitScript = limitScript;
47
+    }
48
+
49
+    @Before("@annotation(rateLimiter)")
50
+    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
51
+    {
52
+        int time = rateLimiter.time();
53
+        int count = rateLimiter.count();
54
+
55
+        String combineKey = getCombineKey(rateLimiter, point);
56
+        List<Object> keys = Collections.singletonList(combineKey);
57
+        try
58
+        {
59
+            Long number = redisTemplate.execute(limitScript, keys, count, time);
60
+            if (StringUtils.isNull(number) || number.intValue() > count)
61
+            {
62
+                throw new ServiceException("访问过于频繁,请稍候再试");
63
+            }
64
+            log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey);
65
+        }
66
+        catch (ServiceException e)
67
+        {
68
+            throw e;
69
+        }
70
+        catch (Exception e)
71
+        {
72
+            throw new RuntimeException("服务器限流异常,请稍候再试");
73
+        }
74
+    }
75
+
76
+    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
77
+    {
78
+        StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
79
+        if (rateLimiter.limitType() == LimitType.IP)
80
+        {
81
+            stringBuffer.append(IpUtils.getIpAddr()).append("-");
82
+        }
83
+        MethodSignature signature = (MethodSignature) point.getSignature();
84
+        Method method = signature.getMethod();
85
+        Class<?> targetClass = method.getDeclaringClass();
86
+        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
87
+        return stringBuffer.toString();
88
+    }
89
+}

+ 30 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/ApplicationConfig.java

@@ -0,0 +1,30 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.util.TimeZone;
4
+import org.mybatis.spring.annotation.MapperScan;
5
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
6
+import org.springframework.context.annotation.Bean;
7
+import org.springframework.context.annotation.Configuration;
8
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
9
+
10
+/**
11
+ * 程序注解配置
12
+ *
13
+ * @author ruoyi
14
+ */
15
+@Configuration
16
+// 表示通过aop框架暴露该代理对象,AopContext能够访问
17
+@EnableAspectJAutoProxy(exposeProxy = true)
18
+// 指定要扫描的Mapper类的包的路径
19
+@MapperScan("com.sundot.airport.**.mapper")
20
+public class ApplicationConfig
21
+{
22
+    /**
23
+     * 时区配置
24
+     */
25
+    @Bean
26
+    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
27
+    {
28
+        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
29
+    }
30
+}

+ 83 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/CaptchaConfig.java

@@ -0,0 +1,83 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.util.Properties;
4
+import org.springframework.context.annotation.Bean;
5
+import org.springframework.context.annotation.Configuration;
6
+import com.google.code.kaptcha.impl.DefaultKaptcha;
7
+import com.google.code.kaptcha.util.Config;
8
+import static com.google.code.kaptcha.Constants.*;
9
+
10
+/**
11
+ * 验证码配置
12
+ * 
13
+ * @author ruoyi
14
+ */
15
+@Configuration
16
+public class CaptchaConfig
17
+{
18
+    @Bean(name = "captchaProducer")
19
+    public DefaultKaptcha getKaptchaBean()
20
+    {
21
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
22
+        Properties properties = new Properties();
23
+        // 是否有边框 默认为true 我们可以自己设置yes,no
24
+        properties.setProperty(KAPTCHA_BORDER, "yes");
25
+        // 验证码文本字符颜色 默认为Color.BLACK
26
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
27
+        // 验证码图片宽度 默认为200
28
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
29
+        // 验证码图片高度 默认为50
30
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
31
+        // 验证码文本字符大小 默认为40
32
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
33
+        // KAPTCHA_SESSION_KEY
34
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
35
+        // 验证码文本字符长度 默认为5
36
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
37
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
38
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
39
+        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
40
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
41
+        Config config = new Config(properties);
42
+        defaultKaptcha.setConfig(config);
43
+        return defaultKaptcha;
44
+    }
45
+
46
+    @Bean(name = "captchaProducerMath")
47
+    public DefaultKaptcha getKaptchaBeanMath()
48
+    {
49
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
50
+        Properties properties = new Properties();
51
+        // 是否有边框 默认为true 我们可以自己设置yes,no
52
+        properties.setProperty(KAPTCHA_BORDER, "yes");
53
+        // 边框颜色 默认为Color.BLACK
54
+        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
55
+        // 验证码文本字符颜色 默认为Color.BLACK
56
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
57
+        // 验证码图片宽度 默认为200
58
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
59
+        // 验证码图片高度 默认为50
60
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
61
+        // 验证码文本字符大小 默认为40
62
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
63
+        // KAPTCHA_SESSION_KEY
64
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
65
+        // 验证码文本生成器
66
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.sundot.airport.framework.config.KaptchaTextCreator");
67
+        // 验证码文本字符间距 默认为2
68
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
69
+        // 验证码文本字符长度 默认为5
70
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
71
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
72
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
73
+        // 验证码噪点颜色 默认为Color.BLACK
74
+        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
75
+        // 干扰实现类
76
+        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
77
+        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
78
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
79
+        Config config = new Config(properties);
80
+        defaultKaptcha.setConfig(config);
81
+        return defaultKaptcha;
82
+    }
83
+}

+ 126 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/DruidConfig.java

@@ -0,0 +1,126 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.io.IOException;
4
+import java.util.HashMap;
5
+import java.util.Map;
6
+import javax.servlet.Filter;
7
+import javax.servlet.FilterChain;
8
+import javax.servlet.ServletException;
9
+import javax.servlet.ServletRequest;
10
+import javax.servlet.ServletResponse;
11
+import javax.sql.DataSource;
12
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
13
+import org.springframework.boot.context.properties.ConfigurationProperties;
14
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
15
+import org.springframework.context.annotation.Bean;
16
+import org.springframework.context.annotation.Configuration;
17
+import org.springframework.context.annotation.Primary;
18
+import com.alibaba.druid.pool.DruidDataSource;
19
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
20
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
21
+import com.alibaba.druid.util.Utils;
22
+import com.sundot.airport.common.enums.DataSourceType;
23
+import com.sundot.airport.common.utils.spring.SpringUtils;
24
+import com.sundot.airport.framework.config.properties.DruidProperties;
25
+import com.sundot.airport.framework.datasource.DynamicDataSource;
26
+
27
+/**
28
+ * druid 配置多数据源
29
+ * 
30
+ * @author ruoyi
31
+ */
32
+@Configuration
33
+public class DruidConfig
34
+{
35
+    @Bean
36
+    @ConfigurationProperties("spring.datasource.druid.master")
37
+    public DataSource masterDataSource(DruidProperties druidProperties)
38
+    {
39
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
40
+        return druidProperties.dataSource(dataSource);
41
+    }
42
+
43
+    @Bean
44
+    @ConfigurationProperties("spring.datasource.druid.slave")
45
+    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
46
+    public DataSource slaveDataSource(DruidProperties druidProperties)
47
+    {
48
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
49
+        return druidProperties.dataSource(dataSource);
50
+    }
51
+
52
+    @Bean(name = "dynamicDataSource")
53
+    @Primary
54
+    public DynamicDataSource dataSource(DataSource masterDataSource)
55
+    {
56
+        Map<Object, Object> targetDataSources = new HashMap<>();
57
+        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
58
+        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
59
+        return new DynamicDataSource(masterDataSource, targetDataSources);
60
+    }
61
+    
62
+    /**
63
+     * 设置数据源
64
+     * 
65
+     * @param targetDataSources 备选数据源集合
66
+     * @param sourceName 数据源名称
67
+     * @param beanName bean名称
68
+     */
69
+    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
70
+    {
71
+        try
72
+        {
73
+            DataSource dataSource = SpringUtils.getBean(beanName);
74
+            targetDataSources.put(sourceName, dataSource);
75
+        }
76
+        catch (Exception e)
77
+        {
78
+        }
79
+    }
80
+
81
+    /**
82
+     * 去除监控页面底部的广告
83
+     */
84
+    @SuppressWarnings({ "rawtypes", "unchecked" })
85
+    @Bean
86
+    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
87
+    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
88
+    {
89
+        // 获取web监控页面的参数
90
+        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
91
+        // 提取common.js的配置路径
92
+        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
93
+        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
94
+        final String filePath = "support/http/resources/js/common.js";
95
+        // 创建filter进行过滤
96
+        Filter filter = new Filter()
97
+        {
98
+            @Override
99
+            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
100
+            {
101
+            }
102
+            @Override
103
+            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
104
+                    throws IOException, ServletException
105
+            {
106
+                chain.doFilter(request, response);
107
+                // 重置缓冲区,响应头不会被重置
108
+                response.resetBuffer();
109
+                // 获取common.js
110
+                String text = Utils.readFromResource(filePath);
111
+                // 正则替换banner, 除去底部的广告信息
112
+                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
113
+                text = text.replaceAll("powered.*?shrek.wang</a>", "");
114
+                response.getWriter().write(text);
115
+            }
116
+            @Override
117
+            public void destroy()
118
+            {
119
+            }
120
+        };
121
+        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
122
+        registrationBean.setFilter(filter);
123
+        registrationBean.addUrlPatterns(commonJsPattern);
124
+        return registrationBean;
125
+    }
126
+}

+ 52 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,52 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.nio.charset.Charset;
4
+import org.springframework.data.redis.serializer.RedisSerializer;
5
+import org.springframework.data.redis.serializer.SerializationException;
6
+import com.alibaba.fastjson2.JSON;
7
+import com.alibaba.fastjson2.JSONReader;
8
+import com.alibaba.fastjson2.JSONWriter;
9
+import com.alibaba.fastjson2.filter.Filter;
10
+import com.sundot.airport.common.constant.Constants;
11
+
12
+/**
13
+ * Redis使用FastJson序列化
14
+ * 
15
+ * @author ruoyi
16
+ */
17
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
18
+{
19
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
20
+
21
+    static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
22
+
23
+    private Class<T> clazz;
24
+
25
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
26
+    {
27
+        super();
28
+        this.clazz = clazz;
29
+    }
30
+
31
+    @Override
32
+    public byte[] serialize(T t) throws SerializationException
33
+    {
34
+        if (t == null)
35
+        {
36
+            return new byte[0];
37
+        }
38
+        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
39
+    }
40
+
41
+    @Override
42
+    public T deserialize(byte[] bytes) throws SerializationException
43
+    {
44
+        if (bytes == null || bytes.length <= 0)
45
+        {
46
+            return null;
47
+        }
48
+        String str = new String(bytes, DEFAULT_CHARSET);
49
+
50
+        return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
51
+    }
52
+}

+ 58 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/FilterConfig.java

@@ -0,0 +1,58 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+import javax.servlet.DispatcherType;
6
+import org.springframework.beans.factory.annotation.Value;
7
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
8
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
9
+import org.springframework.context.annotation.Bean;
10
+import org.springframework.context.annotation.Configuration;
11
+import com.sundot.airport.common.filter.RepeatableFilter;
12
+import com.sundot.airport.common.filter.XssFilter;
13
+import com.sundot.airport.common.utils.StringUtils;
14
+
15
+/**
16
+ * Filter配置
17
+ *
18
+ * @author ruoyi
19
+ */
20
+@Configuration
21
+public class FilterConfig
22
+{
23
+    @Value("${xss.excludes}")
24
+    private String excludes;
25
+
26
+    @Value("${xss.urlPatterns}")
27
+    private String urlPatterns;
28
+
29
+    @SuppressWarnings({ "rawtypes", "unchecked" })
30
+    @Bean
31
+    @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
32
+    public FilterRegistrationBean xssFilterRegistration()
33
+    {
34
+        FilterRegistrationBean registration = new FilterRegistrationBean();
35
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
36
+        registration.setFilter(new XssFilter());
37
+        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
38
+        registration.setName("xssFilter");
39
+        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
40
+        Map<String, String> initParameters = new HashMap<String, String>();
41
+        initParameters.put("excludes", excludes);
42
+        registration.setInitParameters(initParameters);
43
+        return registration;
44
+    }
45
+
46
+    @SuppressWarnings({ "rawtypes", "unchecked" })
47
+    @Bean
48
+    public FilterRegistrationBean someFilterRegistration()
49
+    {
50
+        FilterRegistrationBean registration = new FilterRegistrationBean();
51
+        registration.setFilter(new RepeatableFilter());
52
+        registration.addUrlPatterns("/*");
53
+        registration.setName("repeatableFilter");
54
+        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
55
+        return registration;
56
+    }
57
+
58
+}

+ 43 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/I18nConfig.java

@@ -0,0 +1,43 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import org.springframework.context.annotation.Bean;
4
+import org.springframework.context.annotation.Configuration;
5
+import org.springframework.web.servlet.LocaleResolver;
6
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
7
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
9
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
10
+import com.sundot.airport.common.constant.Constants;
11
+
12
+/**
13
+ * 资源文件配置加载
14
+ * 
15
+ * @author ruoyi
16
+ */
17
+@Configuration
18
+public class I18nConfig implements WebMvcConfigurer
19
+{
20
+    @Bean
21
+    public LocaleResolver localeResolver()
22
+    {
23
+        SessionLocaleResolver slr = new SessionLocaleResolver();
24
+        // 默认语言
25
+        slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
26
+        return slr;
27
+    }
28
+
29
+    @Bean
30
+    public LocaleChangeInterceptor localeChangeInterceptor()
31
+    {
32
+        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
33
+        // 参数名
34
+        lci.setParamName("lang");
35
+        return lci;
36
+    }
37
+
38
+    @Override
39
+    public void addInterceptors(InterceptorRegistry registry)
40
+    {
41
+        registry.addInterceptor(localeChangeInterceptor());
42
+    }
43
+}

+ 68 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/KaptchaTextCreator.java

@@ -0,0 +1,68 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.util.Random;
4
+import com.google.code.kaptcha.text.impl.DefaultTextCreator;
5
+
6
+/**
7
+ * 验证码文本生成器
8
+ *
9
+ * @author ruoyi
10
+ */
11
+public class KaptchaTextCreator extends DefaultTextCreator
12
+{
13
+    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
14
+
15
+    @Override
16
+    public String getText()
17
+    {
18
+        Integer result = 0;
19
+        Random random = new Random();
20
+        int x = random.nextInt(10);
21
+        int y = random.nextInt(10);
22
+        StringBuilder suChinese = new StringBuilder();
23
+        int randomoperands = random.nextInt(3);
24
+        if (randomoperands == 0)
25
+        {
26
+            result = x * y;
27
+            suChinese.append(CNUMBERS[x]);
28
+            suChinese.append("*");
29
+            suChinese.append(CNUMBERS[y]);
30
+        }
31
+        else if (randomoperands == 1)
32
+        {
33
+            if ((x != 0) && y % x == 0)
34
+            {
35
+                result = y / x;
36
+                suChinese.append(CNUMBERS[y]);
37
+                suChinese.append("/");
38
+                suChinese.append(CNUMBERS[x]);
39
+            }
40
+            else
41
+            {
42
+                result = x + y;
43
+                suChinese.append(CNUMBERS[x]);
44
+                suChinese.append("+");
45
+                suChinese.append(CNUMBERS[y]);
46
+            }
47
+        }
48
+        else
49
+        {
50
+            if (x >= y)
51
+            {
52
+                result = x - y;
53
+                suChinese.append(CNUMBERS[x]);
54
+                suChinese.append("-");
55
+                suChinese.append(CNUMBERS[y]);
56
+            }
57
+            else
58
+            {
59
+                result = y - x;
60
+                suChinese.append(CNUMBERS[y]);
61
+                suChinese.append("-");
62
+                suChinese.append(CNUMBERS[x]);
63
+            }
64
+        }
65
+        suChinese.append("=?@" + result);
66
+        return suChinese.toString();
67
+    }
68
+}

+ 132 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/MyBatisConfig.java

@@ -0,0 +1,132 @@
1
+//package com.sundot.airport.framework.config;
2
+//
3
+//import java.io.IOException;
4
+//import java.util.ArrayList;
5
+//import java.util.Arrays;
6
+//import java.util.HashSet;
7
+//import java.util.List;
8
+//import javax.sql.DataSource;
9
+//import org.apache.ibatis.io.VFS;
10
+//import org.apache.ibatis.session.SqlSessionFactory;
11
+//import org.mybatis.spring.SqlSessionFactoryBean;
12
+//import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
13
+//import org.springframework.beans.factory.annotation.Autowired;
14
+//import org.springframework.context.annotation.Bean;
15
+//import org.springframework.context.annotation.Configuration;
16
+//import org.springframework.core.env.Environment;
17
+//import org.springframework.core.io.DefaultResourceLoader;
18
+//import org.springframework.core.io.Resource;
19
+//import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
20
+//import org.springframework.core.io.support.ResourcePatternResolver;
21
+//import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
22
+//import org.springframework.core.type.classreading.MetadataReader;
23
+//import org.springframework.core.type.classreading.MetadataReaderFactory;
24
+//import org.springframework.util.ClassUtils;
25
+//import com.sundot.airport.common.utils.StringUtils;
26
+//
27
+///**
28
+// * Mybatis支持*匹配扫描包
29
+// *
30
+// * @author ruoyi
31
+// */
32
+//@Configuration
33
+//public class MyBatisConfig
34
+//{
35
+//    @Autowired
36
+//    private Environment env;
37
+//
38
+//    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
39
+//
40
+//    public static String setTypeAliasesPackage(String typeAliasesPackage)
41
+//    {
42
+//        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
43
+//        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
44
+//        List<String> allResult = new ArrayList<String>();
45
+//        try
46
+//        {
47
+//            for (String aliasesPackage : typeAliasesPackage.split(","))
48
+//            {
49
+//                List<String> result = new ArrayList<String>();
50
+//                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
51
+//                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
52
+//                Resource[] resources = resolver.getResources(aliasesPackage);
53
+//                if (resources != null && resources.length > 0)
54
+//                {
55
+//                    MetadataReader metadataReader = null;
56
+//                    for (Resource resource : resources)
57
+//                    {
58
+//                        if (resource.isReadable())
59
+//                        {
60
+//                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
61
+//                            try
62
+//                            {
63
+//                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
64
+//                            }
65
+//                            catch (ClassNotFoundException e)
66
+//                            {
67
+//                                e.printStackTrace();
68
+//                            }
69
+//                        }
70
+//                    }
71
+//                }
72
+//                if (result.size() > 0)
73
+//                {
74
+//                    HashSet<String> hashResult = new HashSet<String>(result);
75
+//                    allResult.addAll(hashResult);
76
+//                }
77
+//            }
78
+//            if (allResult.size() > 0)
79
+//            {
80
+//                typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
81
+//            }
82
+//            else
83
+//            {
84
+//                throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
85
+//            }
86
+//        }
87
+//        catch (IOException e)
88
+//        {
89
+//            e.printStackTrace();
90
+//        }
91
+//        return typeAliasesPackage;
92
+//    }
93
+//
94
+//    public Resource[] resolveMapperLocations(String[] mapperLocations)
95
+//    {
96
+//        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
97
+//        List<Resource> resources = new ArrayList<Resource>();
98
+//        if (mapperLocations != null)
99
+//        {
100
+//            for (String mapperLocation : mapperLocations)
101
+//            {
102
+//                try
103
+//                {
104
+//                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
105
+//                    resources.addAll(Arrays.asList(mappers));
106
+//                }
107
+//                catch (IOException e)
108
+//                {
109
+//                    // ignore
110
+//                }
111
+//            }
112
+//        }
113
+//        return resources.toArray(new Resource[resources.size()]);
114
+//    }
115
+//
116
+//    @Bean
117
+//    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
118
+//    {
119
+//        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
120
+//        String mapperLocations = env.getProperty("mybatis.mapperLocations");
121
+//        String configLocation = env.getProperty("mybatis.configLocation");
122
+//        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
123
+//        VFS.addImplClass(SpringBootVFS.class);
124
+//
125
+//        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
126
+//        sessionFactory.setDataSource(dataSource);
127
+//        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
128
+//        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
129
+//        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
130
+//        return sessionFactory.getObject();
131
+//    }
132
+//}

+ 57 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/MybatisPlusConfig.java

@@ -0,0 +1,57 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import com.baomidou.mybatisplus.annotation.DbType;
4
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
5
+import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
6
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
7
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
8
+import org.springframework.context.annotation.Bean;
9
+import org.springframework.context.annotation.Configuration;
10
+import org.springframework.transaction.annotation.EnableTransactionManagement;
11
+
12
+/**
13
+ * Mybatis Plus 配置
14
+ *
15
+ * @author ruoyi
16
+ */
17
+@EnableTransactionManagement(proxyTargetClass = true)
18
+@Configuration
19
+public class MybatisPlusConfig {
20
+    @Bean
21
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
22
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
23
+        // 分页插件
24
+        interceptor.addInnerInterceptor(paginationInnerInterceptor());
25
+        // 乐观锁插件
26
+        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
27
+        // 阻断插件
28
+        interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
29
+        return interceptor;
30
+    }
31
+
32
+    /**
33
+     * 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html
34
+     */
35
+    public PaginationInnerInterceptor paginationInnerInterceptor() {
36
+        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
37
+        // 设置数据库类型为mysql
38
+        paginationInnerInterceptor.setDbType(DbType.MYSQL);
39
+        // 设置最大单页限制数量,默认 500 条,-1 不受限制
40
+        paginationInnerInterceptor.setMaxLimit(-1L);
41
+        return paginationInnerInterceptor;
42
+    }
43
+
44
+    /**
45
+     * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html
46
+     */
47
+    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
48
+        return new OptimisticLockerInnerInterceptor();
49
+    }
50
+
51
+    /**
52
+     * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html
53
+     */
54
+    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
55
+        return new BlockAttackInnerInterceptor();
56
+    }
57
+}

+ 69 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/RedisConfig.java

@@ -0,0 +1,69 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import org.springframework.cache.annotation.CachingConfigurerSupport;
4
+import org.springframework.cache.annotation.EnableCaching;
5
+import org.springframework.context.annotation.Bean;
6
+import org.springframework.context.annotation.Configuration;
7
+import org.springframework.data.redis.connection.RedisConnectionFactory;
8
+import org.springframework.data.redis.core.RedisTemplate;
9
+import org.springframework.data.redis.core.script.DefaultRedisScript;
10
+import org.springframework.data.redis.serializer.StringRedisSerializer;
11
+
12
+/**
13
+ * redis配置
14
+ * 
15
+ * @author ruoyi
16
+ */
17
+@Configuration
18
+@EnableCaching
19
+public class RedisConfig extends CachingConfigurerSupport
20
+{
21
+    @Bean
22
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
23
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
24
+    {
25
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
26
+        template.setConnectionFactory(connectionFactory);
27
+
28
+        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
29
+
30
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
31
+        template.setKeySerializer(new StringRedisSerializer());
32
+        template.setValueSerializer(serializer);
33
+
34
+        // Hash的key也采用StringRedisSerializer的序列化方式
35
+        template.setHashKeySerializer(new StringRedisSerializer());
36
+        template.setHashValueSerializer(serializer);
37
+
38
+        template.afterPropertiesSet();
39
+        return template;
40
+    }
41
+
42
+    @Bean
43
+    public DefaultRedisScript<Long> limitScript()
44
+    {
45
+        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
46
+        redisScript.setScriptText(limitScriptText());
47
+        redisScript.setResultType(Long.class);
48
+        return redisScript;
49
+    }
50
+
51
+    /**
52
+     * 限流脚本
53
+     */
54
+    private String limitScriptText()
55
+    {
56
+        return "local key = KEYS[1]\n" +
57
+                "local count = tonumber(ARGV[1])\n" +
58
+                "local time = tonumber(ARGV[2])\n" +
59
+                "local current = redis.call('get', key);\n" +
60
+                "if current and tonumber(current) > count then\n" +
61
+                "    return tonumber(current);\n" +
62
+                "end\n" +
63
+                "current = redis.call('incr', key)\n" +
64
+                "if tonumber(current) == 1 then\n" +
65
+                "    redis.call('expire', key, time)\n" +
66
+                "end\n" +
67
+                "return tonumber(current);";
68
+    }
69
+}

+ 72 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/ResourcesConfig.java

@@ -0,0 +1,72 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import java.util.concurrent.TimeUnit;
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+import org.springframework.context.annotation.Bean;
6
+import org.springframework.context.annotation.Configuration;
7
+import org.springframework.http.CacheControl;
8
+import org.springframework.web.cors.CorsConfiguration;
9
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
10
+import org.springframework.web.filter.CorsFilter;
11
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
12
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
13
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
14
+import com.sundot.airport.common.config.RuoYiConfig;
15
+import com.sundot.airport.common.constant.Constants;
16
+import com.sundot.airport.framework.interceptor.RepeatSubmitInterceptor;
17
+
18
+/**
19
+ * 通用配置
20
+ * 
21
+ * @author ruoyi
22
+ */
23
+@Configuration
24
+public class ResourcesConfig implements WebMvcConfigurer
25
+{
26
+    @Autowired
27
+    private RepeatSubmitInterceptor repeatSubmitInterceptor;
28
+
29
+    @Override
30
+    public void addResourceHandlers(ResourceHandlerRegistry registry)
31
+    {
32
+        /** 本地文件上传路径 */
33
+        registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
34
+                .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
35
+
36
+        /** swagger配置 */
37
+        registry.addResourceHandler("/swagger-ui/**")
38
+                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
39
+                .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
40
+    }
41
+
42
+    /**
43
+     * 自定义拦截规则
44
+     */
45
+    @Override
46
+    public void addInterceptors(InterceptorRegistry registry)
47
+    {
48
+        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
49
+    }
50
+
51
+    /**
52
+     * 跨域配置
53
+     */
54
+    @Bean
55
+    public CorsFilter corsFilter()
56
+    {
57
+        CorsConfiguration config = new CorsConfiguration();
58
+        // 设置访问源地址
59
+        config.addAllowedOriginPattern("*");
60
+        // 设置访问源请求头
61
+        config.addAllowedHeader("*");
62
+        // 设置访问源请求方法
63
+        config.addAllowedMethod("*");
64
+        // 有效期 1800秒
65
+        config.setMaxAge(1800L);
66
+        // 添加映射路径,拦截一切请求
67
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
68
+        source.registerCorsConfiguration("/**", config);
69
+        // 返回新的CorsFilter
70
+        return new CorsFilter(source);
71
+    }
72
+}

+ 139 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/SecurityConfig.java

@@ -0,0 +1,139 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import org.springframework.beans.factory.annotation.Autowired;
4
+import org.springframework.context.annotation.Bean;
5
+import org.springframework.context.annotation.Configuration;
6
+import org.springframework.http.HttpMethod;
7
+import org.springframework.security.authentication.AuthenticationManager;
8
+import org.springframework.security.authentication.ProviderManager;
9
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
10
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
11
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
12
+import org.springframework.security.config.http.SessionCreationPolicy;
13
+import org.springframework.security.core.userdetails.UserDetailsService;
14
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
15
+import org.springframework.security.web.SecurityFilterChain;
16
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
17
+import org.springframework.security.web.authentication.logout.LogoutFilter;
18
+import org.springframework.web.filter.CorsFilter;
19
+import com.sundot.airport.framework.config.properties.PermitAllUrlProperties;
20
+import com.sundot.airport.framework.security.filter.JwtAuthenticationTokenFilter;
21
+import com.sundot.airport.framework.security.handle.AuthenticationEntryPointImpl;
22
+import com.sundot.airport.framework.security.handle.LogoutSuccessHandlerImpl;
23
+
24
+/**
25
+ * spring security配置
26
+ * 
27
+ * @author ruoyi
28
+ */
29
+@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
30
+@Configuration
31
+public class SecurityConfig
32
+{
33
+    /**
34
+     * 自定义用户认证逻辑
35
+     */
36
+    @Autowired
37
+    private UserDetailsService userDetailsService;
38
+    
39
+    /**
40
+     * 认证失败处理类
41
+     */
42
+    @Autowired
43
+    private AuthenticationEntryPointImpl unauthorizedHandler;
44
+
45
+    /**
46
+     * 退出处理类
47
+     */
48
+    @Autowired
49
+    private LogoutSuccessHandlerImpl logoutSuccessHandler;
50
+
51
+    /**
52
+     * token认证过滤器
53
+     */
54
+    @Autowired
55
+    private JwtAuthenticationTokenFilter authenticationTokenFilter;
56
+    
57
+    /**
58
+     * 跨域过滤器
59
+     */
60
+    @Autowired
61
+    private CorsFilter corsFilter;
62
+
63
+    /**
64
+     * 允许匿名访问的地址
65
+     */
66
+    @Autowired
67
+    private PermitAllUrlProperties permitAllUrl;
68
+
69
+    /**
70
+     * 身份验证实现
71
+     */
72
+    @Bean
73
+    public AuthenticationManager authenticationManager()
74
+    {
75
+        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
76
+        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
77
+        daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
78
+        return new ProviderManager(daoAuthenticationProvider);
79
+    }
80
+
81
+    /**
82
+     * anyRequest          |   匹配所有请求路径
83
+     * access              |   SpringEl表达式结果为true时可以访问
84
+     * anonymous           |   匿名可以访问
85
+     * denyAll             |   用户不能访问
86
+     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
87
+     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
88
+     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
89
+     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
90
+     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
91
+     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
92
+     * permitAll           |   用户可以任意访问
93
+     * rememberMe          |   允许通过remember-me登录的用户访问
94
+     * authenticated       |   用户登录后可访问
95
+     */
96
+    @Bean
97
+    protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception
98
+    {
99
+        return httpSecurity
100
+            // CSRF禁用,因为不使用session
101
+            .csrf(csrf -> csrf.disable())
102
+            // 禁用HTTP响应标头
103
+            .headers((headersCustomizer) -> {
104
+                headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
105
+            })
106
+            // 认证失败处理类
107
+            .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
108
+            // 基于token,所以不需要session
109
+            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
110
+            // 注解标记允许匿名访问的url
111
+            .authorizeHttpRequests((requests) -> {
112
+                permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
113
+                // 对于登录login 注册register 验证码captchaImage 允许匿名访问
114
+                requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
115
+                    // 静态资源,可匿名访问
116
+                    .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
117
+                    .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
118
+                    // 除上面外的所有请求全部需要鉴权认证
119
+                    .anyRequest().authenticated();
120
+            })
121
+            // 添加Logout filter
122
+            .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
123
+            // 添加JWT filter
124
+            .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
125
+            // 添加CORS filter
126
+            .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
127
+            .addFilterBefore(corsFilter, LogoutFilter.class)
128
+            .build();
129
+    }
130
+
131
+    /**
132
+     * 强散列哈希加密实现
133
+     */
134
+    @Bean
135
+    public BCryptPasswordEncoder bCryptPasswordEncoder()
136
+    {
137
+        return new BCryptPasswordEncoder();
138
+    }
139
+}

+ 48 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/ServerConfig.java

@@ -0,0 +1,48 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import javax.servlet.http.HttpServletRequest;
4
+
5
+import cn.hutool.core.util.StrUtil;
6
+import org.springframework.stereotype.Component;
7
+import com.sundot.airport.common.utils.ServletUtils;
8
+
9
+/**
10
+ * 服务相关配置
11
+ *
12
+ * @author ruoyi
13
+ */
14
+@Component
15
+public class ServerConfig {
16
+    /**
17
+     * 获取完整的请求路径,包括:域名,端口,上下文访问路径
18
+     *
19
+     * @return 服务地址
20
+     */
21
+    public String getUrl() {
22
+        HttpServletRequest request = ServletUtils.getRequest();
23
+        return getDomain(request);
24
+    }
25
+
26
+    public static String getDomain(HttpServletRequest request) {
27
+        StringBuffer url = request.getRequestURL();
28
+        String contextPath = request.getServletContext().getContextPath();
29
+        url.delete(url.length() - request.getRequestURI().length(), url.length());
30
+
31
+        // 如果 URL 以 / 结尾,去掉它(避免出现 http://example.com/:9011)
32
+        if (url.charAt(url.length() - 1) == '/') {
33
+            url.deleteCharAt(url.length() - 1);
34
+        }
35
+        // 获取当前请求的端口
36
+        int currentPort = request.getServerPort();
37
+        // 如果是80或443端口(HTTP/HTTPS默认端口),则强制使用9011端口
38
+        if (!StrUtil.equals("http://192.168.3.221", url) && (currentPort == 80 || currentPort == 443)) {
39
+            int protocolEnd = url.indexOf("://") + 3;
40
+            int portStart = url.indexOf(":", protocolEnd);
41
+            if (portStart < 0) {
42
+                // 没有端口,添加端口
43
+                url.insert(url.length(), ":9011");
44
+            }
45
+        }
46
+        return url.append(contextPath).toString();
47
+    }
48
+}

+ 63 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/ThreadPoolConfig.java

@@ -0,0 +1,63 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import com.sundot.airport.common.utils.Threads;
4
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
5
+import org.springframework.context.annotation.Bean;
6
+import org.springframework.context.annotation.Configuration;
7
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
8
+import java.util.concurrent.ScheduledExecutorService;
9
+import java.util.concurrent.ScheduledThreadPoolExecutor;
10
+import java.util.concurrent.ThreadPoolExecutor;
11
+
12
+/**
13
+ * 线程池配置
14
+ *
15
+ * @author ruoyi
16
+ **/
17
+@Configuration
18
+public class ThreadPoolConfig
19
+{
20
+    // 核心线程池大小
21
+    private int corePoolSize = 50;
22
+
23
+    // 最大可创建的线程数
24
+    private int maxPoolSize = 200;
25
+
26
+    // 队列最大长度
27
+    private int queueCapacity = 1000;
28
+
29
+    // 线程池维护线程所允许的空闲时间
30
+    private int keepAliveSeconds = 300;
31
+
32
+    @Bean(name = "threadPoolTaskExecutor")
33
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
34
+    {
35
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
36
+        executor.setMaxPoolSize(maxPoolSize);
37
+        executor.setCorePoolSize(corePoolSize);
38
+        executor.setQueueCapacity(queueCapacity);
39
+        executor.setKeepAliveSeconds(keepAliveSeconds);
40
+        // 线程池对拒绝任务(无线程可用)的处理策略
41
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
42
+        return executor;
43
+    }
44
+
45
+    /**
46
+     * 执行周期性或定时任务
47
+     */
48
+    @Bean(name = "scheduledExecutorService")
49
+    protected ScheduledExecutorService scheduledExecutorService()
50
+    {
51
+        return new ScheduledThreadPoolExecutor(corePoolSize,
52
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
53
+                new ThreadPoolExecutor.CallerRunsPolicy())
54
+        {
55
+            @Override
56
+            protected void afterExecute(Runnable r, Throwable t)
57
+            {
58
+                super.afterExecute(r, t);
59
+                Threads.printException(r, t);
60
+            }
61
+        };
62
+    }
63
+}

+ 27 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/WebAdminInterceptorConfig.java

@@ -0,0 +1,27 @@
1
+package com.sundot.airport.framework.config;
2
+
3
+import com.sundot.airport.framework.interceptor.RequestSourceInterceptor;
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+import org.springframework.context.annotation.Configuration;
6
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
7
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8
+
9
+/**
10
+ * 拦截器配置
11
+ *
12
+ * @author ruoyi
13
+ */
14
+@Configuration
15
+public class WebAdminInterceptorConfig implements WebMvcConfigurer {
16
+
17
+    @Autowired
18
+    private RequestSourceInterceptor requestSourceInterceptor;
19
+
20
+    @Override
21
+    public void addInterceptors(InterceptorRegistry registry) {
22
+        registry.addInterceptor(requestSourceInterceptor)
23
+                .addPathPatterns("/**")
24
+                .excludePathPatterns("/captchaImage", "/login", "/logout");
25
+    }
26
+
27
+}

+ 89 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/properties/DruidProperties.java

@@ -0,0 +1,89 @@
1
+package com.sundot.airport.framework.config.properties;
2
+
3
+import org.springframework.beans.factory.annotation.Value;
4
+import org.springframework.context.annotation.Configuration;
5
+import com.alibaba.druid.pool.DruidDataSource;
6
+
7
+/**
8
+ * druid 配置属性
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+@Configuration
13
+public class DruidProperties
14
+{
15
+    @Value("${spring.datasource.druid.initialSize}")
16
+    private int initialSize;
17
+
18
+    @Value("${spring.datasource.druid.minIdle}")
19
+    private int minIdle;
20
+
21
+    @Value("${spring.datasource.druid.maxActive}")
22
+    private int maxActive;
23
+
24
+    @Value("${spring.datasource.druid.maxWait}")
25
+    private int maxWait;
26
+
27
+    @Value("${spring.datasource.druid.connectTimeout}")
28
+    private int connectTimeout;
29
+
30
+    @Value("${spring.datasource.druid.socketTimeout}")
31
+    private int socketTimeout;
32
+
33
+    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
34
+    private int timeBetweenEvictionRunsMillis;
35
+
36
+    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
37
+    private int minEvictableIdleTimeMillis;
38
+
39
+    @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
40
+    private int maxEvictableIdleTimeMillis;
41
+
42
+    @Value("${spring.datasource.druid.validationQuery}")
43
+    private String validationQuery;
44
+
45
+    @Value("${spring.datasource.druid.testWhileIdle}")
46
+    private boolean testWhileIdle;
47
+
48
+    @Value("${spring.datasource.druid.testOnBorrow}")
49
+    private boolean testOnBorrow;
50
+
51
+    @Value("${spring.datasource.druid.testOnReturn}")
52
+    private boolean testOnReturn;
53
+
54
+    public DruidDataSource dataSource(DruidDataSource datasource)
55
+    {
56
+        /** 配置初始化大小、最小、最大 */
57
+        datasource.setInitialSize(initialSize);
58
+        datasource.setMaxActive(maxActive);
59
+        datasource.setMinIdle(minIdle);
60
+
61
+        /** 配置获取连接等待超时的时间 */
62
+        datasource.setMaxWait(maxWait);
63
+        
64
+        /** 配置驱动连接超时时间,检测数据库建立连接的超时时间,单位是毫秒 */
65
+        datasource.setConnectTimeout(connectTimeout);
66
+        
67
+        /** 配置网络超时时间,等待数据库操作完成的网络超时时间,单位是毫秒 */
68
+        datasource.setSocketTimeout(socketTimeout);
69
+
70
+        /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
71
+        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
72
+
73
+        /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */
74
+        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
75
+        datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
76
+
77
+        /**
78
+         * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
79
+         */
80
+        datasource.setValidationQuery(validationQuery);
81
+        /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
82
+        datasource.setTestWhileIdle(testWhileIdle);
83
+        /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
84
+        datasource.setTestOnBorrow(testOnBorrow);
85
+        /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
86
+        datasource.setTestOnReturn(testOnReturn);
87
+        return datasource;
88
+    }
89
+}

+ 73 - 0
airport-framework/src/main/java/com/sundot/airport/framework/config/properties/PermitAllUrlProperties.java

@@ -0,0 +1,73 @@
1
+package com.sundot.airport.framework.config.properties;
2
+
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+import java.util.Map;
6
+import java.util.Objects;
7
+import java.util.Optional;
8
+import java.util.regex.Pattern;
9
+import org.apache.commons.lang3.RegExUtils;
10
+import org.springframework.beans.BeansException;
11
+import org.springframework.beans.factory.InitializingBean;
12
+import org.springframework.context.ApplicationContext;
13
+import org.springframework.context.ApplicationContextAware;
14
+import org.springframework.context.annotation.Configuration;
15
+import org.springframework.core.annotation.AnnotationUtils;
16
+import org.springframework.web.method.HandlerMethod;
17
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
18
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
19
+import com.sundot.airport.common.annotation.Anonymous;
20
+
21
+/**
22
+ * 设置Anonymous注解允许匿名访问的url
23
+ * 
24
+ * @author ruoyi
25
+ */
26
+@Configuration
27
+public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
28
+{
29
+    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
30
+
31
+    private ApplicationContext applicationContext;
32
+
33
+    private List<String> urls = new ArrayList<>();
34
+
35
+    public String ASTERISK = "*";
36
+
37
+    @Override
38
+    public void afterPropertiesSet()
39
+    {
40
+        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
41
+        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
42
+
43
+        map.keySet().forEach(info -> {
44
+            HandlerMethod handlerMethod = map.get(info);
45
+
46
+            // 获取方法上边的注解 替代path variable 为 *
47
+            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
48
+            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
49
+                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
50
+
51
+            // 获取类上边的注解, 替代path variable 为 *
52
+            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
53
+            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
54
+                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
55
+        });
56
+    }
57
+
58
+    @Override
59
+    public void setApplicationContext(ApplicationContext context) throws BeansException
60
+    {
61
+        this.applicationContext = context;
62
+    }
63
+
64
+    public List<String> getUrls()
65
+    {
66
+        return urls;
67
+    }
68
+
69
+    public void setUrls(List<String> urls)
70
+    {
71
+        this.urls = urls;
72
+    }
73
+}

+ 26 - 0
airport-framework/src/main/java/com/sundot/airport/framework/datasource/DynamicDataSource.java

@@ -0,0 +1,26 @@
1
+package com.sundot.airport.framework.datasource;
2
+
3
+import java.util.Map;
4
+import javax.sql.DataSource;
5
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
6
+
7
+/**
8
+ * 动态数据源
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+public class DynamicDataSource extends AbstractRoutingDataSource
13
+{
14
+    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
15
+    {
16
+        super.setDefaultTargetDataSource(defaultTargetDataSource);
17
+        super.setTargetDataSources(targetDataSources);
18
+        super.afterPropertiesSet();
19
+    }
20
+
21
+    @Override
22
+    protected Object determineCurrentLookupKey()
23
+    {
24
+        return DynamicDataSourceContextHolder.getDataSourceType();
25
+    }
26
+}

+ 45 - 0
airport-framework/src/main/java/com/sundot/airport/framework/datasource/DynamicDataSourceContextHolder.java

@@ -0,0 +1,45 @@
1
+package com.sundot.airport.framework.datasource;
2
+
3
+import org.slf4j.Logger;
4
+import org.slf4j.LoggerFactory;
5
+
6
+/**
7
+ * 数据源切换处理
8
+ * 
9
+ * @author ruoyi
10
+ */
11
+public class DynamicDataSourceContextHolder
12
+{
13
+    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
14
+
15
+    /**
16
+     * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
17
+     * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
18
+     */
19
+    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
20
+
21
+    /**
22
+     * 设置数据源的变量
23
+     */
24
+    public static void setDataSourceType(String dsType)
25
+    {
26
+        log.info("切换到{}数据源", dsType);
27
+        CONTEXT_HOLDER.set(dsType);
28
+    }
29
+
30
+    /**
31
+     * 获得数据源的变量
32
+     */
33
+    public static String getDataSourceType()
34
+    {
35
+        return CONTEXT_HOLDER.get();
36
+    }
37
+
38
+    /**
39
+     * 清空数据源变量
40
+     */
41
+    public static void clearDataSourceType()
42
+    {
43
+        CONTEXT_HOLDER.remove();
44
+    }
45
+}

+ 56 - 0
airport-framework/src/main/java/com/sundot/airport/framework/interceptor/RepeatSubmitInterceptor.java

@@ -0,0 +1,56 @@
1
+package com.sundot.airport.framework.interceptor;
2
+
3
+import java.lang.reflect.Method;
4
+import javax.servlet.http.HttpServletRequest;
5
+import javax.servlet.http.HttpServletResponse;
6
+import org.springframework.stereotype.Component;
7
+import org.springframework.web.method.HandlerMethod;
8
+import org.springframework.web.servlet.HandlerInterceptor;
9
+import com.alibaba.fastjson2.JSON;
10
+import com.sundot.airport.common.annotation.RepeatSubmit;
11
+import com.sundot.airport.common.core.domain.AjaxResult;
12
+import com.sundot.airport.common.utils.ServletUtils;
13
+
14
+/**
15
+ * 防止重复提交拦截器
16
+ *
17
+ * @author ruoyi
18
+ */
19
+@Component
20
+public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
21
+{
22
+    @Override
23
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
24
+    {
25
+        if (handler instanceof HandlerMethod)
26
+        {
27
+            HandlerMethod handlerMethod = (HandlerMethod) handler;
28
+            Method method = handlerMethod.getMethod();
29
+            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
30
+            if (annotation != null)
31
+            {
32
+                if (this.isRepeatSubmit(request, annotation))
33
+                {
34
+                    AjaxResult ajaxResult = AjaxResult.error(annotation.message());
35
+                    ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
36
+                    return false;
37
+                }
38
+            }
39
+            return true;
40
+        }
41
+        else
42
+        {
43
+            return true;
44
+        }
45
+    }
46
+
47
+    /**
48
+     * 验证是否重复提交由子类实现具体的防重复提交的规则
49
+     *
50
+     * @param request 请求信息
51
+     * @param annotation 防重复注解参数
52
+     * @return 结果
53
+     * @throws Exception
54
+     */
55
+    public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
56
+}

+ 70 - 0
airport-framework/src/main/java/com/sundot/airport/framework/interceptor/RequestSourceInterceptor.java

@@ -0,0 +1,70 @@
1
+package com.sundot.airport.framework.interceptor;
2
+
3
+import com.sundot.airport.common.constant.HttpStatus;
4
+import com.sundot.airport.common.core.domain.entity.SysRole;
5
+import com.sundot.airport.common.core.domain.model.LoginUser;
6
+import com.sundot.airport.common.enums.RoleTypeEnum;
7
+import com.sundot.airport.common.exception.ServiceException;
8
+import com.sundot.airport.common.utils.SecurityUtils;
9
+import org.apache.commons.lang3.StringUtils;
10
+import org.springframework.stereotype.Component;
11
+import org.springframework.web.servlet.HandlerInterceptor;
12
+
13
+import javax.servlet.http.HttpServletRequest;
14
+import javax.servlet.http.HttpServletResponse;
15
+import java.util.List;
16
+import java.util.Set;
17
+import java.util.stream.Collectors;
18
+
19
+/**
20
+ * 请求来源拦截器
21
+ * 仅超级管理员、站长、质检科、科长角色可访问web端
22
+ *
23
+ * @author ruoyi
24
+ */
25
+@Component
26
+public class RequestSourceInterceptor implements HandlerInterceptor {
27
+
28
+    /**
29
+     * 请求来源头
30
+     */
31
+    private static final String REQUEST_SOURCE_HEADER = "X-Request-Source";
32
+    /**
33
+     * PC端标识
34
+     */
35
+    private static final String SOURCE_WEB = "web";
36
+    /**
37
+     * 移动端标识
38
+     */
39
+    private static final String SOURCE_MOBILE = "mobile";
40
+
41
+    /**
42
+     * 请求处理之前执行
43
+     */
44
+    @Override
45
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
46
+        String requestSource = request.getHeader(REQUEST_SOURCE_HEADER);
47
+
48
+        // 移动端请求或未指定来源,走原有逻辑
49
+        if (SOURCE_MOBILE.equals(requestSource) || StringUtils.isEmpty(requestSource)) {
50
+            return true;
51
+        }
52
+
53
+        // WEB端请求需要权限验证
54
+        if (SOURCE_WEB.equals(requestSource)) {
55
+            LoginUser loginUser = SecurityUtils.getLoginUser();
56
+            if (loginUser == null) {
57
+                throw new ServiceException("用户未登录", HttpStatus.UNAUTHORIZED);
58
+            }
59
+
60
+            List<SysRole> sysRoleList = loginUser.getUser().getRoles();
61
+            Set<String> roles = sysRoleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
62
+            if (!roles.contains(RoleTypeEnum.admin.getCode()) && !roles.contains(RoleTypeEnum.test.getCode()) && !roles.contains(RoleTypeEnum.zhijianke.getCode()) && !roles.contains(RoleTypeEnum.kezhang.getCode())) {
63
+                throw new ServiceException("仅超级管理员、站长、质检科、科长角色可访问web端", HttpStatus.FORBIDDEN);
64
+            }
65
+        }
66
+
67
+        return true;
68
+    }
69
+
70
+}

+ 110 - 0
airport-framework/src/main/java/com/sundot/airport/framework/interceptor/impl/SameUrlDataInterceptor.java

@@ -0,0 +1,110 @@
1
+package com.sundot.airport.framework.interceptor.impl;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+import java.util.concurrent.TimeUnit;
6
+import javax.servlet.http.HttpServletRequest;
7
+import org.springframework.beans.factory.annotation.Autowired;
8
+import org.springframework.beans.factory.annotation.Value;
9
+import org.springframework.stereotype.Component;
10
+import com.alibaba.fastjson2.JSON;
11
+import com.sundot.airport.common.annotation.RepeatSubmit;
12
+import com.sundot.airport.common.constant.CacheConstants;
13
+import com.sundot.airport.common.core.redis.RedisCache;
14
+import com.sundot.airport.common.filter.RepeatedlyRequestWrapper;
15
+import com.sundot.airport.common.utils.StringUtils;
16
+import com.sundot.airport.common.utils.http.HttpHelper;
17
+import com.sundot.airport.framework.interceptor.RepeatSubmitInterceptor;
18
+
19
+/**
20
+ * 判断请求url和数据是否和上一次相同,
21
+ * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
22
+ * 
23
+ * @author ruoyi
24
+ */
25
+@Component
26
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
27
+{
28
+    public final String REPEAT_PARAMS = "repeatParams";
29
+
30
+    public final String REPEAT_TIME = "repeatTime";
31
+
32
+    // 令牌自定义标识
33
+    @Value("${token.header}")
34
+    private String header;
35
+
36
+    @Autowired
37
+    private RedisCache redisCache;
38
+
39
+    @SuppressWarnings("unchecked")
40
+    @Override
41
+    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
42
+    {
43
+        String nowParams = "";
44
+        if (request instanceof RepeatedlyRequestWrapper)
45
+        {
46
+            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
47
+            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
48
+        }
49
+
50
+        // body参数为空,获取Parameter的数据
51
+        if (StringUtils.isEmpty(nowParams))
52
+        {
53
+            nowParams = JSON.toJSONString(request.getParameterMap());
54
+        }
55
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
56
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
57
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
58
+
59
+        // 请求地址(作为存放cache的key值)
60
+        String url = request.getRequestURI();
61
+
62
+        // 唯一值(没有消息头则使用请求地址)
63
+        String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
64
+
65
+        // 唯一标识(指定key + url + 消息头)
66
+        String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
67
+
68
+        Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
69
+        if (sessionObj != null)
70
+        {
71
+            Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
72
+            if (sessionMap.containsKey(url))
73
+            {
74
+                Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
75
+                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
76
+                {
77
+                    return true;
78
+                }
79
+            }
80
+        }
81
+        Map<String, Object> cacheMap = new HashMap<String, Object>();
82
+        cacheMap.put(url, nowDataMap);
83
+        redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
84
+        return false;
85
+    }
86
+
87
+    /**
88
+     * 判断参数是否相同
89
+     */
90
+    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
91
+    {
92
+        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
93
+        String preParams = (String) preMap.get(REPEAT_PARAMS);
94
+        return nowParams.equals(preParams);
95
+    }
96
+
97
+    /**
98
+     * 判断两次间隔时间
99
+     */
100
+    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
101
+    {
102
+        long time1 = (Long) nowMap.get(REPEAT_TIME);
103
+        long time2 = (Long) preMap.get(REPEAT_TIME);
104
+        if ((time1 - time2) < interval)
105
+        {
106
+            return true;
107
+        }
108
+        return false;
109
+    }
110
+}

+ 55 - 0
airport-framework/src/main/java/com/sundot/airport/framework/manager/AsyncManager.java

@@ -0,0 +1,55 @@
1
+package com.sundot.airport.framework.manager;
2
+
3
+import java.util.TimerTask;
4
+import java.util.concurrent.ScheduledExecutorService;
5
+import java.util.concurrent.TimeUnit;
6
+import com.sundot.airport.common.utils.Threads;
7
+import com.sundot.airport.common.utils.spring.SpringUtils;
8
+
9
+/**
10
+ * 异步任务管理器
11
+ * 
12
+ * @author ruoyi
13
+ */
14
+public class AsyncManager
15
+{
16
+    /**
17
+     * 操作延迟10毫秒
18
+     */
19
+    private final int OPERATE_DELAY_TIME = 10;
20
+
21
+    /**
22
+     * 异步操作任务调度线程池
23
+     */
24
+    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
25
+
26
+    /**
27
+     * 单例模式
28
+     */
29
+    private AsyncManager(){}
30
+
31
+    private static AsyncManager me = new AsyncManager();
32
+
33
+    public static AsyncManager me()
34
+    {
35
+        return me;
36
+    }
37
+
38
+    /**
39
+     * 执行任务
40
+     * 
41
+     * @param task 任务
42
+     */
43
+    public void execute(TimerTask task)
44
+    {
45
+        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
46
+    }
47
+
48
+    /**
49
+     * 停止任务线程池
50
+     */
51
+    public void shutdown()
52
+    {
53
+        Threads.shutdownAndAwaitTermination(executor);
54
+    }
55
+}

+ 39 - 0
airport-framework/src/main/java/com/sundot/airport/framework/manager/ShutdownManager.java

@@ -0,0 +1,39 @@
1
+package com.sundot.airport.framework.manager;
2
+
3
+import org.slf4j.Logger;
4
+import org.slf4j.LoggerFactory;
5
+import org.springframework.stereotype.Component;
6
+import javax.annotation.PreDestroy;
7
+
8
+/**
9
+ * 确保应用退出时能关闭后台线程
10
+ *
11
+ * @author ruoyi
12
+ */
13
+@Component
14
+public class ShutdownManager
15
+{
16
+    private static final Logger logger = LoggerFactory.getLogger("sys-user");
17
+
18
+    @PreDestroy
19
+    public void destroy()
20
+    {
21
+        shutdownAsyncManager();
22
+    }
23
+
24
+    /**
25
+     * 停止异步执行任务
26
+     */
27
+    private void shutdownAsyncManager()
28
+    {
29
+        try
30
+        {
31
+            logger.info("====关闭后台任务任务线程池====");
32
+            AsyncManager.me().shutdown();
33
+        }
34
+        catch (Exception e)
35
+        {
36
+            logger.error(e.getMessage(), e);
37
+        }
38
+    }
39
+}

+ 102 - 0
airport-framework/src/main/java/com/sundot/airport/framework/manager/factory/AsyncFactory.java

@@ -0,0 +1,102 @@
1
+package com.sundot.airport.framework.manager.factory;
2
+
3
+import java.util.TimerTask;
4
+import org.slf4j.Logger;
5
+import org.slf4j.LoggerFactory;
6
+import com.sundot.airport.common.constant.Constants;
7
+import com.sundot.airport.common.utils.LogUtils;
8
+import com.sundot.airport.common.utils.ServletUtils;
9
+import com.sundot.airport.common.utils.StringUtils;
10
+import com.sundot.airport.common.utils.ip.AddressUtils;
11
+import com.sundot.airport.common.utils.ip.IpUtils;
12
+import com.sundot.airport.common.utils.spring.SpringUtils;
13
+import com.sundot.airport.system.domain.SysLogininfor;
14
+import com.sundot.airport.system.domain.SysOperLog;
15
+import com.sundot.airport.system.service.ISysLogininforService;
16
+import com.sundot.airport.system.service.ISysOperLogService;
17
+import eu.bitwalker.useragentutils.UserAgent;
18
+
19
+/**
20
+ * 异步工厂(产生任务用)
21
+ * 
22
+ * @author ruoyi
23
+ */
24
+public class AsyncFactory
25
+{
26
+    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
27
+
28
+    /**
29
+     * 记录登录信息
30
+     * 
31
+     * @param username 用户名
32
+     * @param status 状态
33
+     * @param message 消息
34
+     * @param args 列表
35
+     * @return 任务task
36
+     */
37
+    public static TimerTask recordLogininfor(final String username, final String status, final String message,
38
+            final Object... args)
39
+    {
40
+        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
41
+        final String ip = IpUtils.getIpAddr();
42
+        return new TimerTask()
43
+        {
44
+            @Override
45
+            public void run()
46
+            {
47
+                String address = AddressUtils.getRealAddressByIP(ip);
48
+                StringBuilder s = new StringBuilder();
49
+                s.append(LogUtils.getBlock(ip));
50
+                s.append(address);
51
+                s.append(LogUtils.getBlock(username));
52
+                s.append(LogUtils.getBlock(status));
53
+                s.append(LogUtils.getBlock(message));
54
+                // 打印信息到日志
55
+                sys_user_logger.info(s.toString(), args);
56
+                // 获取客户端操作系统
57
+                String os = userAgent.getOperatingSystem().getName();
58
+                // 获取客户端浏览器
59
+                String browser = userAgent.getBrowser().getName();
60
+                // 封装对象
61
+                SysLogininfor logininfor = new SysLogininfor();
62
+                logininfor.setUserName(username);
63
+                logininfor.setIpaddr(ip);
64
+                logininfor.setLoginLocation(address);
65
+                logininfor.setBrowser(browser);
66
+                logininfor.setOs(os);
67
+                logininfor.setMsg(message);
68
+                // 日志状态
69
+                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
70
+                {
71
+                    logininfor.setStatus(Constants.SUCCESS);
72
+                }
73
+                else if (Constants.LOGIN_FAIL.equals(status))
74
+                {
75
+                    logininfor.setStatus(Constants.FAIL);
76
+                }
77
+                // 插入数据
78
+                SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
79
+            }
80
+        };
81
+    }
82
+
83
+    /**
84
+     * 操作日志记录
85
+     * 
86
+     * @param operLog 操作日志信息
87
+     * @return 任务task
88
+     */
89
+    public static TimerTask recordOper(final SysOperLog operLog)
90
+    {
91
+        return new TimerTask()
92
+        {
93
+            @Override
94
+            public void run()
95
+            {
96
+                // 远程查询操作地点
97
+                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
98
+                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
99
+            }
100
+        };
101
+    }
102
+}

+ 28 - 0
airport-framework/src/main/java/com/sundot/airport/framework/security/context/AuthenticationContextHolder.java

@@ -0,0 +1,28 @@
1
+package com.sundot.airport.framework.security.context;
2
+
3
+import org.springframework.security.core.Authentication;
4
+
5
+/**
6
+ * 身份验证信息
7
+ * 
8
+ * @author ruoyi
9
+ */
10
+public class AuthenticationContextHolder
11
+{
12
+    private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
13
+
14
+    public static Authentication getContext()
15
+    {
16
+        return contextHolder.get();
17
+    }
18
+
19
+    public static void setContext(Authentication context)
20
+    {
21
+        contextHolder.set(context);
22
+    }
23
+
24
+    public static void clearContext()
25
+    {
26
+        contextHolder.remove();
27
+    }
28
+}

+ 27 - 0
airport-framework/src/main/java/com/sundot/airport/framework/security/context/PermissionContextHolder.java

@@ -0,0 +1,27 @@
1
+package com.sundot.airport.framework.security.context;
2
+
3
+import org.springframework.web.context.request.RequestAttributes;
4
+import org.springframework.web.context.request.RequestContextHolder;
5
+import com.sundot.airport.common.core.text.Convert;
6
+
7
+/**
8
+ * 权限信息
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+public class PermissionContextHolder
13
+{
14
+    private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
15
+
16
+    public static void setContext(String permission)
17
+    {
18
+        RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
19
+                RequestAttributes.SCOPE_REQUEST);
20
+    }
21
+
22
+    public static String getContext()
23
+    {
24
+        return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
25
+                RequestAttributes.SCOPE_REQUEST));
26
+    }
27
+}

+ 44 - 0
airport-framework/src/main/java/com/sundot/airport/framework/security/filter/JwtAuthenticationTokenFilter.java

@@ -0,0 +1,44 @@
1
+package com.sundot.airport.framework.security.filter;
2
+
3
+import java.io.IOException;
4
+import javax.servlet.FilterChain;
5
+import javax.servlet.ServletException;
6
+import javax.servlet.http.HttpServletRequest;
7
+import javax.servlet.http.HttpServletResponse;
8
+import org.springframework.beans.factory.annotation.Autowired;
9
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
10
+import org.springframework.security.core.context.SecurityContextHolder;
11
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
12
+import org.springframework.stereotype.Component;
13
+import org.springframework.web.filter.OncePerRequestFilter;
14
+import com.sundot.airport.common.core.domain.model.LoginUser;
15
+import com.sundot.airport.common.utils.SecurityUtils;
16
+import com.sundot.airport.common.utils.StringUtils;
17
+import com.sundot.airport.framework.web.service.TokenService;
18
+
19
+/**
20
+ * token过滤器 验证token有效性
21
+ * 
22
+ * @author ruoyi
23
+ */
24
+@Component
25
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
26
+{
27
+    @Autowired
28
+    private TokenService tokenService;
29
+
30
+    @Override
31
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
32
+            throws ServletException, IOException
33
+    {
34
+        LoginUser loginUser = tokenService.getLoginUser(request);
35
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
36
+        {
37
+            tokenService.verifyToken(loginUser);
38
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
39
+            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
40
+            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
41
+        }
42
+        chain.doFilter(request, response);
43
+    }
44
+}

+ 34 - 0
airport-framework/src/main/java/com/sundot/airport/framework/security/handle/AuthenticationEntryPointImpl.java

@@ -0,0 +1,34 @@
1
+package com.sundot.airport.framework.security.handle;
2
+
3
+import java.io.IOException;
4
+import java.io.Serializable;
5
+import javax.servlet.http.HttpServletRequest;
6
+import javax.servlet.http.HttpServletResponse;
7
+import org.springframework.security.core.AuthenticationException;
8
+import org.springframework.security.web.AuthenticationEntryPoint;
9
+import org.springframework.stereotype.Component;
10
+import com.alibaba.fastjson2.JSON;
11
+import com.sundot.airport.common.constant.HttpStatus;
12
+import com.sundot.airport.common.core.domain.AjaxResult;
13
+import com.sundot.airport.common.utils.ServletUtils;
14
+import com.sundot.airport.common.utils.StringUtils;
15
+
16
+/**
17
+ * 认证失败处理类 返回未授权
18
+ * 
19
+ * @author ruoyi
20
+ */
21
+@Component
22
+public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
23
+{
24
+    private static final long serialVersionUID = -8970718410437077606L;
25
+
26
+    @Override
27
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
28
+            throws IOException
29
+    {
30
+        int code = HttpStatus.UNAUTHORIZED;
31
+        String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
32
+        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
33
+    }
34
+}

+ 53 - 0
airport-framework/src/main/java/com/sundot/airport/framework/security/handle/LogoutSuccessHandlerImpl.java

@@ -0,0 +1,53 @@
1
+package com.sundot.airport.framework.security.handle;
2
+
3
+import java.io.IOException;
4
+import javax.servlet.ServletException;
5
+import javax.servlet.http.HttpServletRequest;
6
+import javax.servlet.http.HttpServletResponse;
7
+import org.springframework.beans.factory.annotation.Autowired;
8
+import org.springframework.context.annotation.Configuration;
9
+import org.springframework.security.core.Authentication;
10
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
11
+import com.alibaba.fastjson2.JSON;
12
+import com.sundot.airport.common.constant.Constants;
13
+import com.sundot.airport.common.core.domain.AjaxResult;
14
+import com.sundot.airport.common.core.domain.model.LoginUser;
15
+import com.sundot.airport.common.utils.MessageUtils;
16
+import com.sundot.airport.common.utils.ServletUtils;
17
+import com.sundot.airport.common.utils.StringUtils;
18
+import com.sundot.airport.framework.manager.AsyncManager;
19
+import com.sundot.airport.framework.manager.factory.AsyncFactory;
20
+import com.sundot.airport.framework.web.service.TokenService;
21
+
22
+/**
23
+ * 自定义退出处理类 返回成功
24
+ * 
25
+ * @author ruoyi
26
+ */
27
+@Configuration
28
+public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
29
+{
30
+    @Autowired
31
+    private TokenService tokenService;
32
+
33
+    /**
34
+     * 退出处理
35
+     * 
36
+     * @return
37
+     */
38
+    @Override
39
+    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
40
+            throws IOException, ServletException
41
+    {
42
+        LoginUser loginUser = tokenService.getLoginUser(request);
43
+        if (StringUtils.isNotNull(loginUser))
44
+        {
45
+            String userName = loginUser.getUsername();
46
+            // 删除用户缓存记录
47
+            tokenService.delLoginUser(loginUser.getToken());
48
+            // 记录用户退出日志
49
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
50
+        }
51
+        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success"))));
52
+    }
53
+}

+ 240 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/domain/Server.java

@@ -0,0 +1,240 @@
1
+package com.sundot.airport.framework.web.domain;
2
+
3
+import java.net.UnknownHostException;
4
+import java.util.LinkedList;
5
+import java.util.List;
6
+import java.util.Properties;
7
+import com.sundot.airport.common.utils.Arith;
8
+import com.sundot.airport.common.utils.ip.IpUtils;
9
+import com.sundot.airport.framework.web.domain.server.Cpu;
10
+import com.sundot.airport.framework.web.domain.server.Jvm;
11
+import com.sundot.airport.framework.web.domain.server.Mem;
12
+import com.sundot.airport.framework.web.domain.server.Sys;
13
+import com.sundot.airport.framework.web.domain.server.SysFile;
14
+import oshi.SystemInfo;
15
+import oshi.hardware.CentralProcessor;
16
+import oshi.hardware.CentralProcessor.TickType;
17
+import oshi.hardware.GlobalMemory;
18
+import oshi.hardware.HardwareAbstractionLayer;
19
+import oshi.software.os.FileSystem;
20
+import oshi.software.os.OSFileStore;
21
+import oshi.software.os.OperatingSystem;
22
+import oshi.util.Util;
23
+
24
+/**
25
+ * 服务器相关信息
26
+ * 
27
+ * @author ruoyi
28
+ */
29
+public class Server
30
+{
31
+    private static final int OSHI_WAIT_SECOND = 1000;
32
+    
33
+    /**
34
+     * CPU相关信息
35
+     */
36
+    private Cpu cpu = new Cpu();
37
+
38
+    /**
39
+     * 內存相关信息
40
+     */
41
+    private Mem mem = new Mem();
42
+
43
+    /**
44
+     * JVM相关信息
45
+     */
46
+    private Jvm jvm = new Jvm();
47
+
48
+    /**
49
+     * 服务器相关信息
50
+     */
51
+    private Sys sys = new Sys();
52
+
53
+    /**
54
+     * 磁盘相关信息
55
+     */
56
+    private List<SysFile> sysFiles = new LinkedList<SysFile>();
57
+
58
+    public Cpu getCpu()
59
+    {
60
+        return cpu;
61
+    }
62
+
63
+    public void setCpu(Cpu cpu)
64
+    {
65
+        this.cpu = cpu;
66
+    }
67
+
68
+    public Mem getMem()
69
+    {
70
+        return mem;
71
+    }
72
+
73
+    public void setMem(Mem mem)
74
+    {
75
+        this.mem = mem;
76
+    }
77
+
78
+    public Jvm getJvm()
79
+    {
80
+        return jvm;
81
+    }
82
+
83
+    public void setJvm(Jvm jvm)
84
+    {
85
+        this.jvm = jvm;
86
+    }
87
+
88
+    public Sys getSys()
89
+    {
90
+        return sys;
91
+    }
92
+
93
+    public void setSys(Sys sys)
94
+    {
95
+        this.sys = sys;
96
+    }
97
+
98
+    public List<SysFile> getSysFiles()
99
+    {
100
+        return sysFiles;
101
+    }
102
+
103
+    public void setSysFiles(List<SysFile> sysFiles)
104
+    {
105
+        this.sysFiles = sysFiles;
106
+    }
107
+
108
+    public void copyTo() throws Exception
109
+    {
110
+        SystemInfo si = new SystemInfo();
111
+        HardwareAbstractionLayer hal = si.getHardware();
112
+
113
+        setCpuInfo(hal.getProcessor());
114
+
115
+        setMemInfo(hal.getMemory());
116
+
117
+        setSysInfo();
118
+
119
+        setJvmInfo();
120
+
121
+        setSysFiles(si.getOperatingSystem());
122
+    }
123
+
124
+    /**
125
+     * 设置CPU信息
126
+     */
127
+    private void setCpuInfo(CentralProcessor processor)
128
+    {
129
+        // CPU信息
130
+        long[] prevTicks = processor.getSystemCpuLoadTicks();
131
+        Util.sleep(OSHI_WAIT_SECOND);
132
+        long[] ticks = processor.getSystemCpuLoadTicks();
133
+        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
134
+        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
135
+        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
136
+        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
137
+        long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
138
+        long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
139
+        long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
140
+        long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
141
+        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
142
+        cpu.setCpuNum(processor.getLogicalProcessorCount());
143
+        cpu.setTotal(totalCpu);
144
+        cpu.setSys(cSys);
145
+        cpu.setUsed(user);
146
+        cpu.setWait(iowait);
147
+        cpu.setFree(idle);
148
+    }
149
+
150
+    /**
151
+     * 设置内存信息
152
+     */
153
+    private void setMemInfo(GlobalMemory memory)
154
+    {
155
+        mem.setTotal(memory.getTotal());
156
+        mem.setUsed(memory.getTotal() - memory.getAvailable());
157
+        mem.setFree(memory.getAvailable());
158
+    }
159
+
160
+    /**
161
+     * 设置服务器信息
162
+     */
163
+    private void setSysInfo()
164
+    {
165
+        Properties props = System.getProperties();
166
+        sys.setComputerName(IpUtils.getHostName());
167
+        sys.setComputerIp(IpUtils.getHostIp());
168
+        sys.setOsName(props.getProperty("os.name"));
169
+        sys.setOsArch(props.getProperty("os.arch"));
170
+        sys.setUserDir(props.getProperty("user.dir"));
171
+    }
172
+
173
+    /**
174
+     * 设置Java虚拟机
175
+     */
176
+    private void setJvmInfo() throws UnknownHostException
177
+    {
178
+        Properties props = System.getProperties();
179
+        jvm.setTotal(Runtime.getRuntime().totalMemory());
180
+        jvm.setMax(Runtime.getRuntime().maxMemory());
181
+        jvm.setFree(Runtime.getRuntime().freeMemory());
182
+        jvm.setVersion(props.getProperty("java.version"));
183
+        jvm.setHome(props.getProperty("java.home"));
184
+    }
185
+
186
+    /**
187
+     * 设置磁盘信息
188
+     */
189
+    private void setSysFiles(OperatingSystem os)
190
+    {
191
+        FileSystem fileSystem = os.getFileSystem();
192
+        List<OSFileStore> fsArray = fileSystem.getFileStores();
193
+        for (OSFileStore fs : fsArray)
194
+        {
195
+            long free = fs.getUsableSpace();
196
+            long total = fs.getTotalSpace();
197
+            long used = total - free;
198
+            SysFile sysFile = new SysFile();
199
+            sysFile.setDirName(fs.getMount());
200
+            sysFile.setSysTypeName(fs.getType());
201
+            sysFile.setTypeName(fs.getName());
202
+            sysFile.setTotal(convertFileSize(total));
203
+            sysFile.setFree(convertFileSize(free));
204
+            sysFile.setUsed(convertFileSize(used));
205
+            sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));
206
+            sysFiles.add(sysFile);
207
+        }
208
+    }
209
+
210
+    /**
211
+     * 字节转换
212
+     * 
213
+     * @param size 字节大小
214
+     * @return 转换后值
215
+     */
216
+    public String convertFileSize(long size)
217
+    {
218
+        long kb = 1024;
219
+        long mb = kb * 1024;
220
+        long gb = mb * 1024;
221
+        if (size >= gb)
222
+        {
223
+            return String.format("%.1f GB", (float) size / gb);
224
+        }
225
+        else if (size >= mb)
226
+        {
227
+            float f = (float) size / mb;
228
+            return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
229
+        }
230
+        else if (size >= kb)
231
+        {
232
+            float f = (float) size / kb;
233
+            return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
234
+        }
235
+        else
236
+        {
237
+            return String.format("%d B", size);
238
+        }
239
+    }
240
+}

+ 101 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Cpu.java

@@ -0,0 +1,101 @@
1
+package com.sundot.airport.framework.web.domain.server;
2
+
3
+import com.sundot.airport.common.utils.Arith;
4
+
5
+/**
6
+ * CPU相关信息
7
+ * 
8
+ * @author ruoyi
9
+ */
10
+public class Cpu
11
+{
12
+    /**
13
+     * 核心数
14
+     */
15
+    private int cpuNum;
16
+
17
+    /**
18
+     * CPU总的使用率
19
+     */
20
+    private double total;
21
+
22
+    /**
23
+     * CPU系统使用率
24
+     */
25
+    private double sys;
26
+
27
+    /**
28
+     * CPU用户使用率
29
+     */
30
+    private double used;
31
+
32
+    /**
33
+     * CPU当前等待率
34
+     */
35
+    private double wait;
36
+
37
+    /**
38
+     * CPU当前空闲率
39
+     */
40
+    private double free;
41
+
42
+    public int getCpuNum()
43
+    {
44
+        return cpuNum;
45
+    }
46
+
47
+    public void setCpuNum(int cpuNum)
48
+    {
49
+        this.cpuNum = cpuNum;
50
+    }
51
+
52
+    public double getTotal()
53
+    {
54
+        return Arith.round(Arith.mul(total, 100), 2);
55
+    }
56
+
57
+    public void setTotal(double total)
58
+    {
59
+        this.total = total;
60
+    }
61
+
62
+    public double getSys()
63
+    {
64
+        return Arith.round(Arith.mul(sys / total, 100), 2);
65
+    }
66
+
67
+    public void setSys(double sys)
68
+    {
69
+        this.sys = sys;
70
+    }
71
+
72
+    public double getUsed()
73
+    {
74
+        return Arith.round(Arith.mul(used / total, 100), 2);
75
+    }
76
+
77
+    public void setUsed(double used)
78
+    {
79
+        this.used = used;
80
+    }
81
+
82
+    public double getWait()
83
+    {
84
+        return Arith.round(Arith.mul(wait / total, 100), 2);
85
+    }
86
+
87
+    public void setWait(double wait)
88
+    {
89
+        this.wait = wait;
90
+    }
91
+
92
+    public double getFree()
93
+    {
94
+        return Arith.round(Arith.mul(free / total, 100), 2);
95
+    }
96
+
97
+    public void setFree(double free)
98
+    {
99
+        this.free = free;
100
+    }
101
+}

+ 130 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Jvm.java

@@ -0,0 +1,130 @@
1
+package com.sundot.airport.framework.web.domain.server;
2
+
3
+import java.lang.management.ManagementFactory;
4
+import com.sundot.airport.common.utils.Arith;
5
+import com.sundot.airport.common.utils.DateUtils;
6
+
7
+/**
8
+ * JVM相关信息
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+public class Jvm
13
+{
14
+    /**
15
+     * 当前JVM占用的内存总数(M)
16
+     */
17
+    private double total;
18
+
19
+    /**
20
+     * JVM最大可用内存总数(M)
21
+     */
22
+    private double max;
23
+
24
+    /**
25
+     * JVM空闲内存(M)
26
+     */
27
+    private double free;
28
+
29
+    /**
30
+     * JDK版本
31
+     */
32
+    private String version;
33
+
34
+    /**
35
+     * JDK路径
36
+     */
37
+    private String home;
38
+
39
+    public double getTotal()
40
+    {
41
+        return Arith.div(total, (1024 * 1024), 2);
42
+    }
43
+
44
+    public void setTotal(double total)
45
+    {
46
+        this.total = total;
47
+    }
48
+
49
+    public double getMax()
50
+    {
51
+        return Arith.div(max, (1024 * 1024), 2);
52
+    }
53
+
54
+    public void setMax(double max)
55
+    {
56
+        this.max = max;
57
+    }
58
+
59
+    public double getFree()
60
+    {
61
+        return Arith.div(free, (1024 * 1024), 2);
62
+    }
63
+
64
+    public void setFree(double free)
65
+    {
66
+        this.free = free;
67
+    }
68
+
69
+    public double getUsed()
70
+    {
71
+        return Arith.div(total - free, (1024 * 1024), 2);
72
+    }
73
+
74
+    public double getUsage()
75
+    {
76
+        return Arith.mul(Arith.div(total - free, total, 4), 100);
77
+    }
78
+
79
+    /**
80
+     * 获取JDK名称
81
+     */
82
+    public String getName()
83
+    {
84
+        return ManagementFactory.getRuntimeMXBean().getVmName();
85
+    }
86
+
87
+    public String getVersion()
88
+    {
89
+        return version;
90
+    }
91
+
92
+    public void setVersion(String version)
93
+    {
94
+        this.version = version;
95
+    }
96
+
97
+    public String getHome()
98
+    {
99
+        return home;
100
+    }
101
+
102
+    public void setHome(String home)
103
+    {
104
+        this.home = home;
105
+    }
106
+
107
+    /**
108
+     * JDK启动时间
109
+     */
110
+    public String getStartTime()
111
+    {
112
+        return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
113
+    }
114
+
115
+    /**
116
+     * JDK运行时间
117
+     */
118
+    public String getRunTime()
119
+    {
120
+        return DateUtils.timeDistance(DateUtils.getNowDate(), DateUtils.getServerStartDate());
121
+    }
122
+
123
+    /**
124
+     * 运行参数
125
+     */
126
+    public String getInputArgs()
127
+    {
128
+        return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
129
+    }
130
+}

+ 61 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Mem.java

@@ -0,0 +1,61 @@
1
+package com.sundot.airport.framework.web.domain.server;
2
+
3
+import com.sundot.airport.common.utils.Arith;
4
+
5
+/**
6
+ * 內存相关信息
7
+ * 
8
+ * @author ruoyi
9
+ */
10
+public class Mem
11
+{
12
+    /**
13
+     * 内存总量
14
+     */
15
+    private double total;
16
+
17
+    /**
18
+     * 已用内存
19
+     */
20
+    private double used;
21
+
22
+    /**
23
+     * 剩余内存
24
+     */
25
+    private double free;
26
+
27
+    public double getTotal()
28
+    {
29
+        return Arith.div(total, (1024 * 1024 * 1024), 2);
30
+    }
31
+
32
+    public void setTotal(long total)
33
+    {
34
+        this.total = total;
35
+    }
36
+
37
+    public double getUsed()
38
+    {
39
+        return Arith.div(used, (1024 * 1024 * 1024), 2);
40
+    }
41
+
42
+    public void setUsed(long used)
43
+    {
44
+        this.used = used;
45
+    }
46
+
47
+    public double getFree()
48
+    {
49
+        return Arith.div(free, (1024 * 1024 * 1024), 2);
50
+    }
51
+
52
+    public void setFree(long free)
53
+    {
54
+        this.free = free;
55
+    }
56
+
57
+    public double getUsage()
58
+    {
59
+        return Arith.mul(Arith.div(used, total, 4), 100);
60
+    }
61
+}

+ 84 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/Sys.java

@@ -0,0 +1,84 @@
1
+package com.sundot.airport.framework.web.domain.server;
2
+
3
+/**
4
+ * 系统相关信息
5
+ * 
6
+ * @author ruoyi
7
+ */
8
+public class Sys
9
+{
10
+    /**
11
+     * 服务器名称
12
+     */
13
+    private String computerName;
14
+
15
+    /**
16
+     * 服务器Ip
17
+     */
18
+    private String computerIp;
19
+
20
+    /**
21
+     * 项目路径
22
+     */
23
+    private String userDir;
24
+
25
+    /**
26
+     * 操作系统
27
+     */
28
+    private String osName;
29
+
30
+    /**
31
+     * 系统架构
32
+     */
33
+    private String osArch;
34
+
35
+    public String getComputerName()
36
+    {
37
+        return computerName;
38
+    }
39
+
40
+    public void setComputerName(String computerName)
41
+    {
42
+        this.computerName = computerName;
43
+    }
44
+
45
+    public String getComputerIp()
46
+    {
47
+        return computerIp;
48
+    }
49
+
50
+    public void setComputerIp(String computerIp)
51
+    {
52
+        this.computerIp = computerIp;
53
+    }
54
+
55
+    public String getUserDir()
56
+    {
57
+        return userDir;
58
+    }
59
+
60
+    public void setUserDir(String userDir)
61
+    {
62
+        this.userDir = userDir;
63
+    }
64
+
65
+    public String getOsName()
66
+    {
67
+        return osName;
68
+    }
69
+
70
+    public void setOsName(String osName)
71
+    {
72
+        this.osName = osName;
73
+    }
74
+
75
+    public String getOsArch()
76
+    {
77
+        return osArch;
78
+    }
79
+
80
+    public void setOsArch(String osArch)
81
+    {
82
+        this.osArch = osArch;
83
+    }
84
+}

+ 114 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/domain/server/SysFile.java

@@ -0,0 +1,114 @@
1
+package com.sundot.airport.framework.web.domain.server;
2
+
3
+/**
4
+ * 系统文件相关信息
5
+ * 
6
+ * @author ruoyi
7
+ */
8
+public class SysFile
9
+{
10
+    /**
11
+     * 盘符路径
12
+     */
13
+    private String dirName;
14
+
15
+    /**
16
+     * 盘符类型
17
+     */
18
+    private String sysTypeName;
19
+
20
+    /**
21
+     * 文件类型
22
+     */
23
+    private String typeName;
24
+
25
+    /**
26
+     * 总大小
27
+     */
28
+    private String total;
29
+
30
+    /**
31
+     * 剩余大小
32
+     */
33
+    private String free;
34
+
35
+    /**
36
+     * 已经使用量
37
+     */
38
+    private String used;
39
+
40
+    /**
41
+     * 资源的使用率
42
+     */
43
+    private double usage;
44
+
45
+    public String getDirName()
46
+    {
47
+        return dirName;
48
+    }
49
+
50
+    public void setDirName(String dirName)
51
+    {
52
+        this.dirName = dirName;
53
+    }
54
+
55
+    public String getSysTypeName()
56
+    {
57
+        return sysTypeName;
58
+    }
59
+
60
+    public void setSysTypeName(String sysTypeName)
61
+    {
62
+        this.sysTypeName = sysTypeName;
63
+    }
64
+
65
+    public String getTypeName()
66
+    {
67
+        return typeName;
68
+    }
69
+
70
+    public void setTypeName(String typeName)
71
+    {
72
+        this.typeName = typeName;
73
+    }
74
+
75
+    public String getTotal()
76
+    {
77
+        return total;
78
+    }
79
+
80
+    public void setTotal(String total)
81
+    {
82
+        this.total = total;
83
+    }
84
+
85
+    public String getFree()
86
+    {
87
+        return free;
88
+    }
89
+
90
+    public void setFree(String free)
91
+    {
92
+        this.free = free;
93
+    }
94
+
95
+    public String getUsed()
96
+    {
97
+        return used;
98
+    }
99
+
100
+    public void setUsed(String used)
101
+    {
102
+        this.used = used;
103
+    }
104
+
105
+    public double getUsage()
106
+    {
107
+        return usage;
108
+    }
109
+
110
+    public void setUsage(double usage)
111
+    {
112
+        this.usage = usage;
113
+    }
114
+}

+ 164 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/exception/GlobalExceptionHandler.java

@@ -0,0 +1,164 @@
1
+package com.sundot.airport.framework.web.exception;
2
+
3
+import javax.servlet.http.HttpServletRequest;
4
+import org.slf4j.Logger;
5
+import org.slf4j.LoggerFactory;
6
+import org.springframework.security.access.AccessDeniedException;
7
+import org.springframework.validation.BindException;
8
+import org.springframework.web.HttpRequestMethodNotSupportedException;
9
+import org.springframework.web.bind.MethodArgumentNotValidException;
10
+import org.springframework.web.bind.MissingPathVariableException;
11
+import org.springframework.web.bind.annotation.ExceptionHandler;
12
+import org.springframework.web.bind.annotation.RestControllerAdvice;
13
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
14
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
15
+import com.sundot.airport.common.constant.HttpStatus;
16
+import com.sundot.airport.common.core.domain.AjaxResult;
17
+import com.sundot.airport.common.core.text.Convert;
18
+import com.sundot.airport.common.exception.DemoModeException;
19
+import com.sundot.airport.common.exception.ServiceException;
20
+import com.sundot.airport.common.utils.StringUtils;
21
+import com.sundot.airport.common.utils.html.EscapeUtil;
22
+
23
+/**
24
+ * 全局异常处理器
25
+ * 
26
+ * @author ruoyi
27
+ */
28
+@RestControllerAdvice
29
+public class GlobalExceptionHandler
30
+{
31
+    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
32
+
33
+    /**
34
+     * 权限校验异常
35
+     */
36
+    @ExceptionHandler(AccessDeniedException.class)
37
+    public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
38
+    {
39
+        String requestURI = request.getRequestURI();
40
+        log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
41
+        return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
42
+    }
43
+
44
+    /**
45
+     * 请求方式不支持
46
+     */
47
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
48
+    public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
49
+            HttpServletRequest request)
50
+    {
51
+        String requestURI = request.getRequestURI();
52
+        log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
53
+        return AjaxResult.error(e.getMessage());
54
+    }
55
+
56
+    /**
57
+     * 业务异常
58
+     */
59
+    @ExceptionHandler(ServiceException.class)
60
+    public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
61
+    {
62
+        log.error(e.getMessage(), e);
63
+        Integer code = e.getCode();
64
+        return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
65
+    }
66
+
67
+    /**
68
+     * 请求路径中缺少必需的路径变量
69
+     */
70
+    @ExceptionHandler(MissingPathVariableException.class)
71
+    public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
72
+    {
73
+        String requestURI = request.getRequestURI();
74
+        log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
75
+        return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
76
+    }
77
+
78
+    /**
79
+     * 请求参数类型不匹配
80
+     */
81
+    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
82
+    public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
83
+    {
84
+        String requestURI = request.getRequestURI();
85
+        String value = Convert.toStr(e.getValue());
86
+        if (StringUtils.isNotEmpty(value))
87
+        {
88
+            value = EscapeUtil.clean(value);
89
+        }
90
+        log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
91
+        return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
92
+    }
93
+
94
+    /**
95
+     * 文件上传大小超限或文件名过长异常
96
+     */
97
+    @ExceptionHandler(MaxUploadSizeExceededException.class)
98
+    public AjaxResult handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request)
99
+    {
100
+        String requestURI = request.getRequestURI();
101
+        log.error("请求地址'{}',文件上传异常.", requestURI, e);
102
+
103
+        // 判断是否是文件名过长导致的错误
104
+        if (e.getMessage() != null && e.getMessage().contains("Header section has more than 512 bytes"))
105
+        {
106
+            return AjaxResult.error("上传失败:文件名过长(包含路径信息)。请重命名文件为较短的名称(建议不超过50个字符),或去掉文件路径信息后重试。");
107
+        }
108
+
109
+        return AjaxResult.error("上传失败:文件大小超出限制,单个文件最大10MB,总请求大小最大20MB。");
110
+    }
111
+
112
+    /**
113
+     * 拦截未知的运行时异常
114
+     */
115
+    @ExceptionHandler(RuntimeException.class)
116
+    public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
117
+    {
118
+        String requestURI = request.getRequestURI();
119
+        log.error("请求地址'{}',发生未知异常.", requestURI, e);
120
+        return AjaxResult.error(e.getMessage());
121
+    }
122
+
123
+    /**
124
+     * 系统异常
125
+     */
126
+    @ExceptionHandler(Exception.class)
127
+    public AjaxResult handleException(Exception e, HttpServletRequest request)
128
+    {
129
+        String requestURI = request.getRequestURI();
130
+        log.error("请求地址'{}',发生系统异常.", requestURI, e);
131
+        return AjaxResult.error(e.getMessage());
132
+    }
133
+
134
+    /**
135
+     * 自定义验证异常
136
+     */
137
+    @ExceptionHandler(BindException.class)
138
+    public AjaxResult handleBindException(BindException e)
139
+    {
140
+        log.error(e.getMessage(), e);
141
+        String message = e.getAllErrors().get(0).getDefaultMessage();
142
+        return AjaxResult.error(message);
143
+    }
144
+
145
+    /**
146
+     * 自定义验证异常
147
+     */
148
+    @ExceptionHandler(MethodArgumentNotValidException.class)
149
+    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
150
+    {
151
+        log.error(e.getMessage(), e);
152
+        String message = e.getBindingResult().getFieldError().getDefaultMessage();
153
+        return AjaxResult.error(message);
154
+    }
155
+
156
+    /**
157
+     * 演示模式异常
158
+     */
159
+    @ExceptionHandler(DemoModeException.class)
160
+    public AjaxResult handleDemoModeException(DemoModeException e)
161
+    {
162
+        return AjaxResult.error("演示模式,不允许操作");
163
+    }
164
+}

+ 159 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/PermissionService.java

@@ -0,0 +1,159 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import java.util.Set;
4
+import org.springframework.stereotype.Service;
5
+import org.springframework.util.CollectionUtils;
6
+import com.sundot.airport.common.constant.Constants;
7
+import com.sundot.airport.common.core.domain.entity.SysRole;
8
+import com.sundot.airport.common.core.domain.model.LoginUser;
9
+import com.sundot.airport.common.utils.SecurityUtils;
10
+import com.sundot.airport.common.utils.StringUtils;
11
+import com.sundot.airport.framework.security.context.PermissionContextHolder;
12
+
13
+/**
14
+ * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母
15
+ * 
16
+ * @author ruoyi
17
+ */
18
+@Service("ss")
19
+public class PermissionService
20
+{
21
+    /**
22
+     * 验证用户是否具备某权限
23
+     * 
24
+     * @param permission 权限字符串
25
+     * @return 用户是否具备某权限
26
+     */
27
+    public boolean hasPermi(String permission)
28
+    {
29
+        if (StringUtils.isEmpty(permission))
30
+        {
31
+            return false;
32
+        }
33
+        LoginUser loginUser = SecurityUtils.getLoginUser();
34
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
35
+        {
36
+            return false;
37
+        }
38
+        PermissionContextHolder.setContext(permission);
39
+        return hasPermissions(loginUser.getPermissions(), permission);
40
+    }
41
+
42
+    /**
43
+     * 验证用户是否不具备某权限,与 hasPermi逻辑相反
44
+     *
45
+     * @param permission 权限字符串
46
+     * @return 用户是否不具备某权限
47
+     */
48
+    public boolean lacksPermi(String permission)
49
+    {
50
+        return hasPermi(permission) != true;
51
+    }
52
+
53
+    /**
54
+     * 验证用户是否具有以下任意一个权限
55
+     *
56
+     * @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
57
+     * @return 用户是否具有以下任意一个权限
58
+     */
59
+    public boolean hasAnyPermi(String permissions)
60
+    {
61
+        if (StringUtils.isEmpty(permissions))
62
+        {
63
+            return false;
64
+        }
65
+        LoginUser loginUser = SecurityUtils.getLoginUser();
66
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
67
+        {
68
+            return false;
69
+        }
70
+        PermissionContextHolder.setContext(permissions);
71
+        Set<String> authorities = loginUser.getPermissions();
72
+        for (String permission : permissions.split(Constants.PERMISSION_DELIMETER))
73
+        {
74
+            if (permission != null && hasPermissions(authorities, permission))
75
+            {
76
+                return true;
77
+            }
78
+        }
79
+        return false;
80
+    }
81
+
82
+    /**
83
+     * 判断用户是否拥有某个角色
84
+     * 
85
+     * @param role 角色字符串
86
+     * @return 用户是否具备某角色
87
+     */
88
+    public boolean hasRole(String role)
89
+    {
90
+        if (StringUtils.isEmpty(role))
91
+        {
92
+            return false;
93
+        }
94
+        LoginUser loginUser = SecurityUtils.getLoginUser();
95
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
96
+        {
97
+            return false;
98
+        }
99
+        for (SysRole sysRole : loginUser.getUser().getRoles())
100
+        {
101
+            String roleKey = sysRole.getRoleKey();
102
+            if (Constants.SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
103
+            {
104
+                return true;
105
+            }
106
+        }
107
+        return false;
108
+    }
109
+
110
+    /**
111
+     * 验证用户是否不具备某角色,与 isRole逻辑相反。
112
+     *
113
+     * @param role 角色名称
114
+     * @return 用户是否不具备某角色
115
+     */
116
+    public boolean lacksRole(String role)
117
+    {
118
+        return hasRole(role) != true;
119
+    }
120
+
121
+    /**
122
+     * 验证用户是否具有以下任意一个角色
123
+     *
124
+     * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
125
+     * @return 用户是否具有以下任意一个角色
126
+     */
127
+    public boolean hasAnyRoles(String roles)
128
+    {
129
+        if (StringUtils.isEmpty(roles))
130
+        {
131
+            return false;
132
+        }
133
+        LoginUser loginUser = SecurityUtils.getLoginUser();
134
+        if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
135
+        {
136
+            return false;
137
+        }
138
+        for (String role : roles.split(Constants.ROLE_DELIMETER))
139
+        {
140
+            if (hasRole(role))
141
+            {
142
+                return true;
143
+            }
144
+        }
145
+        return false;
146
+    }
147
+
148
+    /**
149
+     * 判断是否包含权限
150
+     * 
151
+     * @param permissions 权限列表
152
+     * @param permission 权限字符串
153
+     * @return 用户是否具备某权限
154
+     */
155
+    private boolean hasPermissions(Set<String> permissions, String permission)
156
+    {
157
+        return permissions.contains(Constants.ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
158
+    }
159
+}

+ 181 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysLoginService.java

@@ -0,0 +1,181 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import javax.annotation.Resource;
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+import org.springframework.security.authentication.AuthenticationManager;
6
+import org.springframework.security.authentication.BadCredentialsException;
7
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8
+import org.springframework.security.core.Authentication;
9
+import org.springframework.stereotype.Component;
10
+import com.sundot.airport.common.constant.CacheConstants;
11
+import com.sundot.airport.common.constant.Constants;
12
+import com.sundot.airport.common.constant.UserConstants;
13
+import com.sundot.airport.common.core.domain.entity.SysUser;
14
+import com.sundot.airport.common.core.domain.model.LoginUser;
15
+import com.sundot.airport.common.core.redis.RedisCache;
16
+import com.sundot.airport.common.exception.ServiceException;
17
+import com.sundot.airport.common.exception.user.BlackListException;
18
+import com.sundot.airport.common.exception.user.CaptchaException;
19
+import com.sundot.airport.common.exception.user.CaptchaExpireException;
20
+import com.sundot.airport.common.exception.user.UserNotExistsException;
21
+import com.sundot.airport.common.exception.user.UserPasswordNotMatchException;
22
+import com.sundot.airport.common.utils.DateUtils;
23
+import com.sundot.airport.common.utils.MessageUtils;
24
+import com.sundot.airport.common.utils.StringUtils;
25
+import com.sundot.airport.common.utils.ip.IpUtils;
26
+import com.sundot.airport.framework.manager.AsyncManager;
27
+import com.sundot.airport.framework.manager.factory.AsyncFactory;
28
+import com.sundot.airport.framework.security.context.AuthenticationContextHolder;
29
+import com.sundot.airport.system.service.ISysConfigService;
30
+import com.sundot.airport.system.service.ISysUserService;
31
+
32
+/**
33
+ * 登录校验方法
34
+ * 
35
+ * @author ruoyi
36
+ */
37
+@Component
38
+public class SysLoginService
39
+{
40
+    @Autowired
41
+    private TokenService tokenService;
42
+
43
+    @Resource
44
+    private AuthenticationManager authenticationManager;
45
+
46
+    @Autowired
47
+    private RedisCache redisCache;
48
+    
49
+    @Autowired
50
+    private ISysUserService userService;
51
+
52
+    @Autowired
53
+    private ISysConfigService configService;
54
+
55
+    /**
56
+     * 登录验证
57
+     * 
58
+     * @param username 用户名
59
+     * @param password 密码
60
+     * @param code 验证码
61
+     * @param uuid 唯一标识
62
+     * @return 结果
63
+     */
64
+    public String login(String username, String password, String code, String uuid)
65
+    {
66
+        // 验证码校验
67
+        validateCaptcha(username, code, uuid);
68
+        // 登录前置校验
69
+        loginPreCheck(username, password);
70
+        // 用户验证
71
+        Authentication authentication = null;
72
+        try
73
+        {
74
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
75
+            AuthenticationContextHolder.setContext(authenticationToken);
76
+            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
77
+            authentication = authenticationManager.authenticate(authenticationToken);
78
+        }
79
+        catch (Exception e)
80
+        {
81
+            if (e instanceof BadCredentialsException)
82
+            {
83
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
84
+                throw new UserPasswordNotMatchException();
85
+            }
86
+            else
87
+            {
88
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
89
+                throw new ServiceException(e.getMessage());
90
+            }
91
+        }
92
+        finally
93
+        {
94
+            AuthenticationContextHolder.clearContext();
95
+        }
96
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
97
+        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
98
+        recordLoginInfo(loginUser.getUserId());
99
+        // 生成token
100
+        return tokenService.createToken(loginUser);
101
+    }
102
+
103
+    /**
104
+     * 校验验证码
105
+     * 
106
+     * @param username 用户名
107
+     * @param code 验证码
108
+     * @param uuid 唯一标识
109
+     * @return 结果
110
+     */
111
+    public void validateCaptcha(String username, String code, String uuid)
112
+    {
113
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
114
+        if (captchaEnabled)
115
+        {
116
+            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
117
+            String captcha = redisCache.getCacheObject(verifyKey);
118
+            if (captcha == null)
119
+            {
120
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
121
+                throw new CaptchaExpireException();
122
+            }
123
+            redisCache.deleteObject(verifyKey);
124
+            if (!code.equalsIgnoreCase(captcha))
125
+            {
126
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
127
+                throw new CaptchaException();
128
+            }
129
+        }
130
+    }
131
+
132
+    /**
133
+     * 登录前置校验
134
+     * @param username 用户名
135
+     * @param password 用户密码
136
+     */
137
+    public void loginPreCheck(String username, String password)
138
+    {
139
+        // 用户名或密码为空 错误
140
+        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
141
+        {
142
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
143
+            throw new UserNotExistsException();
144
+        }
145
+        // 密码如果不在指定范围内 错误
146
+        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
147
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
148
+        {
149
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
150
+            throw new UserPasswordNotMatchException();
151
+        }
152
+        // 用户名不在指定范围内 错误
153
+        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
154
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
155
+        {
156
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
157
+            throw new UserPasswordNotMatchException();
158
+        }
159
+        // IP黑名单校验
160
+        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
161
+        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
162
+        {
163
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
164
+            throw new BlackListException();
165
+        }
166
+    }
167
+
168
+    /**
169
+     * 记录登录信息
170
+     *
171
+     * @param userId 用户ID
172
+     */
173
+    public void recordLoginInfo(Long userId)
174
+    {
175
+        SysUser sysUser = new SysUser();
176
+        sysUser.setUserId(userId);
177
+        sysUser.setLoginIp(IpUtils.getIpAddr());
178
+        sysUser.setLoginDate(DateUtils.getNowDate());
179
+        userService.updateUserProfile(sysUser);
180
+    }
181
+}

+ 86 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysPasswordService.java

@@ -0,0 +1,86 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import java.util.concurrent.TimeUnit;
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+import org.springframework.beans.factory.annotation.Value;
6
+import org.springframework.security.core.Authentication;
7
+import org.springframework.stereotype.Component;
8
+import com.sundot.airport.common.constant.CacheConstants;
9
+import com.sundot.airport.common.core.domain.entity.SysUser;
10
+import com.sundot.airport.common.core.redis.RedisCache;
11
+import com.sundot.airport.common.exception.user.UserPasswordNotMatchException;
12
+import com.sundot.airport.common.exception.user.UserPasswordRetryLimitExceedException;
13
+import com.sundot.airport.common.utils.SecurityUtils;
14
+import com.sundot.airport.framework.security.context.AuthenticationContextHolder;
15
+
16
+/**
17
+ * 登录密码方法
18
+ * 
19
+ * @author ruoyi
20
+ */
21
+@Component
22
+public class SysPasswordService
23
+{
24
+    @Autowired
25
+    private RedisCache redisCache;
26
+
27
+    @Value(value = "${user.password.maxRetryCount}")
28
+    private int maxRetryCount;
29
+
30
+    @Value(value = "${user.password.lockTime}")
31
+    private int lockTime;
32
+
33
+    /**
34
+     * 登录账户密码错误次数缓存键名
35
+     * 
36
+     * @param username 用户名
37
+     * @return 缓存键key
38
+     */
39
+    private String getCacheKey(String username)
40
+    {
41
+        return CacheConstants.PWD_ERR_CNT_KEY + username;
42
+    }
43
+
44
+    public void validate(SysUser user)
45
+    {
46
+        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
47
+        String username = usernamePasswordAuthenticationToken.getName();
48
+        String password = usernamePasswordAuthenticationToken.getCredentials().toString();
49
+
50
+        Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
51
+
52
+        if (retryCount == null)
53
+        {
54
+            retryCount = 0;
55
+        }
56
+
57
+        if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
58
+        {
59
+            throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
60
+        }
61
+
62
+        if (!matches(user, password))
63
+        {
64
+            retryCount = retryCount + 1;
65
+            redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
66
+            throw new UserPasswordNotMatchException();
67
+        }
68
+        else
69
+        {
70
+            clearLoginRecordCache(username);
71
+        }
72
+    }
73
+
74
+    public boolean matches(SysUser user, String rawPassword)
75
+    {
76
+        return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
77
+    }
78
+
79
+    public void clearLoginRecordCache(String loginName)
80
+    {
81
+        if (redisCache.hasKey(getCacheKey(loginName)))
82
+        {
83
+            redisCache.deleteObject(getCacheKey(loginName));
84
+        }
85
+    }
86
+}

+ 88 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysPermissionService.java

@@ -0,0 +1,88 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import java.util.HashSet;
4
+import java.util.List;
5
+import java.util.Set;
6
+import org.springframework.beans.factory.annotation.Autowired;
7
+import org.springframework.stereotype.Component;
8
+import org.springframework.util.CollectionUtils;
9
+import com.sundot.airport.common.constant.UserConstants;
10
+import com.sundot.airport.common.core.domain.entity.SysRole;
11
+import com.sundot.airport.common.core.domain.entity.SysUser;
12
+import com.sundot.airport.common.utils.StringUtils;
13
+import com.sundot.airport.system.service.ISysMenuService;
14
+import com.sundot.airport.system.service.ISysRoleService;
15
+
16
+/**
17
+ * 用户权限处理
18
+ * 
19
+ * @author ruoyi
20
+ */
21
+@Component
22
+public class SysPermissionService
23
+{
24
+    @Autowired
25
+    private ISysRoleService roleService;
26
+
27
+    @Autowired
28
+    private ISysMenuService menuService;
29
+
30
+    /**
31
+     * 获取角色数据权限
32
+     * 
33
+     * @param user 用户信息
34
+     * @return 角色权限信息
35
+     */
36
+    public Set<String> getRolePermission(SysUser user)
37
+    {
38
+        Set<String> roles = new HashSet<String>();
39
+        // 管理员拥有所有权限
40
+        if (user.isAdmin())
41
+        {
42
+            roles.add("admin");
43
+        }
44
+        else
45
+        {
46
+            roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
47
+        }
48
+        return roles;
49
+    }
50
+
51
+    /**
52
+     * 获取菜单数据权限
53
+     * 
54
+     * @param user 用户信息
55
+     * @return 菜单权限信息
56
+     */
57
+    public Set<String> getMenuPermission(SysUser user)
58
+    {
59
+        Set<String> perms = new HashSet<String>();
60
+        // 管理员拥有所有权限
61
+        if (user.isAdmin())
62
+        {
63
+            perms.add("*:*:*");
64
+        }
65
+        else
66
+        {
67
+            List<SysRole> roles = user.getRoles();
68
+            if (!CollectionUtils.isEmpty(roles))
69
+            {
70
+                // 多角色设置permissions属性,以便数据权限匹配权限
71
+                for (SysRole role : roles)
72
+                {
73
+                    if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && !role.isAdmin())
74
+                    {
75
+                        Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
76
+                        role.setPermissions(rolePerms);
77
+                        perms.addAll(rolePerms);
78
+                    }
79
+                }
80
+            }
81
+            else
82
+            {
83
+                perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
84
+            }
85
+        }
86
+        return perms;
87
+    }
88
+}

+ 117 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/SysRegisterService.java

@@ -0,0 +1,117 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import org.springframework.beans.factory.annotation.Autowired;
4
+import org.springframework.stereotype.Component;
5
+import com.sundot.airport.common.constant.CacheConstants;
6
+import com.sundot.airport.common.constant.Constants;
7
+import com.sundot.airport.common.constant.UserConstants;
8
+import com.sundot.airport.common.core.domain.entity.SysUser;
9
+import com.sundot.airport.common.core.domain.model.RegisterBody;
10
+import com.sundot.airport.common.core.redis.RedisCache;
11
+import com.sundot.airport.common.exception.user.CaptchaException;
12
+import com.sundot.airport.common.exception.user.CaptchaExpireException;
13
+import com.sundot.airport.common.utils.DateUtils;
14
+import com.sundot.airport.common.utils.MessageUtils;
15
+import com.sundot.airport.common.utils.SecurityUtils;
16
+import com.sundot.airport.common.utils.StringUtils;
17
+import com.sundot.airport.framework.manager.AsyncManager;
18
+import com.sundot.airport.framework.manager.factory.AsyncFactory;
19
+import com.sundot.airport.system.service.ISysConfigService;
20
+import com.sundot.airport.system.service.ISysUserService;
21
+
22
+/**
23
+ * 注册校验方法
24
+ * 
25
+ * @author ruoyi
26
+ */
27
+@Component
28
+public class SysRegisterService
29
+{
30
+    @Autowired
31
+    private ISysUserService userService;
32
+
33
+    @Autowired
34
+    private ISysConfigService configService;
35
+
36
+    @Autowired
37
+    private RedisCache redisCache;
38
+
39
+    /**
40
+     * 注册
41
+     */
42
+    public String register(RegisterBody registerBody)
43
+    {
44
+        String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
45
+        SysUser sysUser = new SysUser();
46
+        sysUser.setUserName(username);
47
+
48
+        // 验证码开关
49
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
50
+        if (captchaEnabled)
51
+        {
52
+            validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
53
+        }
54
+
55
+        if (StringUtils.isEmpty(username))
56
+        {
57
+            msg = "用户名不能为空";
58
+        }
59
+        else if (StringUtils.isEmpty(password))
60
+        {
61
+            msg = "用户密码不能为空";
62
+        }
63
+        else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
64
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
65
+        {
66
+            msg = "账户长度必须在2到20个字符之间";
67
+        }
68
+        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
69
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
70
+        {
71
+            msg = "密码长度必须在5到20个字符之间";
72
+        }
73
+        else if (!userService.checkUserNameUnique(sysUser))
74
+        {
75
+            msg = "保存用户'" + username + "'失败,注册账号已存在";
76
+        }
77
+        else
78
+        {
79
+            sysUser.setNickName(username);
80
+            sysUser.setPwdUpdateDate(DateUtils.getNowDate());
81
+            sysUser.setPassword(SecurityUtils.encryptPassword(password));
82
+            boolean regFlag = userService.registerUser(sysUser);
83
+            if (!regFlag)
84
+            {
85
+                msg = "注册失败,请联系系统管理人员";
86
+            }
87
+            else
88
+            {
89
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
90
+            }
91
+        }
92
+        return msg;
93
+    }
94
+
95
+    /**
96
+     * 校验验证码
97
+     * 
98
+     * @param username 用户名
99
+     * @param code 验证码
100
+     * @param uuid 唯一标识
101
+     * @return 结果
102
+     */
103
+    public void validateCaptcha(String username, String code, String uuid)
104
+    {
105
+        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
106
+        String captcha = redisCache.getCacheObject(verifyKey);
107
+        redisCache.deleteObject(verifyKey);
108
+        if (captcha == null)
109
+        {
110
+            throw new CaptchaExpireException();
111
+        }
112
+        if (!code.equalsIgnoreCase(captcha))
113
+        {
114
+            throw new CaptchaException();
115
+        }
116
+    }
117
+}

+ 232 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/TokenService.java

@@ -0,0 +1,232 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+import java.util.concurrent.TimeUnit;
6
+import javax.servlet.http.HttpServletRequest;
7
+import org.slf4j.Logger;
8
+import org.slf4j.LoggerFactory;
9
+import org.springframework.beans.factory.annotation.Autowired;
10
+import org.springframework.beans.factory.annotation.Value;
11
+import org.springframework.stereotype.Component;
12
+import com.sundot.airport.common.constant.CacheConstants;
13
+import com.sundot.airport.common.constant.Constants;
14
+import com.sundot.airport.common.core.domain.model.LoginUser;
15
+import com.sundot.airport.common.core.redis.RedisCache;
16
+import com.sundot.airport.common.utils.ServletUtils;
17
+import com.sundot.airport.common.utils.StringUtils;
18
+import com.sundot.airport.common.utils.ip.AddressUtils;
19
+import com.sundot.airport.common.utils.ip.IpUtils;
20
+import com.sundot.airport.common.utils.uuid.IdUtils;
21
+import eu.bitwalker.useragentutils.UserAgent;
22
+import io.jsonwebtoken.Claims;
23
+import io.jsonwebtoken.Jwts;
24
+import io.jsonwebtoken.SignatureAlgorithm;
25
+
26
+/**
27
+ * token验证处理
28
+ * 
29
+ * @author ruoyi
30
+ */
31
+@Component
32
+public class TokenService
33
+{
34
+    private static final Logger log = LoggerFactory.getLogger(TokenService.class);
35
+
36
+    // 令牌自定义标识
37
+    @Value("${token.header}")
38
+    private String header;
39
+
40
+    // 令牌秘钥
41
+    @Value("${token.secret}")
42
+    private String secret;
43
+
44
+    // 令牌有效期(默认30分钟)
45
+    @Value("${token.expireTime}")
46
+    private int expireTime;
47
+
48
+    protected static final long MILLIS_SECOND = 1000;
49
+
50
+    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
51
+
52
+    private static final Long MILLIS_MINUTE_TWENTY = 12 * 60 * 60 * 1000L;
53
+
54
+    @Autowired
55
+    private RedisCache redisCache;
56
+
57
+    /**
58
+     * 获取用户身份信息
59
+     * 
60
+     * @return 用户信息
61
+     */
62
+    public LoginUser getLoginUser(HttpServletRequest request)
63
+    {
64
+        // 获取请求携带的令牌
65
+        String token = getToken(request);
66
+        if (StringUtils.isNotEmpty(token))
67
+        {
68
+            try
69
+            {
70
+                Claims claims = parseToken(token);
71
+                // 解析对应的权限以及用户信息
72
+                String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
73
+                String userKey = getTokenKey(uuid);
74
+                LoginUser user = redisCache.getCacheObject(userKey);
75
+                return user;
76
+            }
77
+            catch (Exception e)
78
+            {
79
+                log.error("获取用户信息异常'{}'", e.getMessage());
80
+            }
81
+        }
82
+        return null;
83
+    }
84
+
85
+    /**
86
+     * 设置用户身份信息
87
+     */
88
+    public void setLoginUser(LoginUser loginUser)
89
+    {
90
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
91
+        {
92
+            refreshToken(loginUser);
93
+        }
94
+    }
95
+
96
+    /**
97
+     * 删除用户身份信息
98
+     */
99
+    public void delLoginUser(String token)
100
+    {
101
+        if (StringUtils.isNotEmpty(token))
102
+        {
103
+            String userKey = getTokenKey(token);
104
+            redisCache.deleteObject(userKey);
105
+        }
106
+    }
107
+
108
+    /**
109
+     * 创建令牌
110
+     * 
111
+     * @param loginUser 用户信息
112
+     * @return 令牌
113
+     */
114
+    public String createToken(LoginUser loginUser)
115
+    {
116
+        String token = IdUtils.fastUUID();
117
+        loginUser.setToken(token);
118
+        setUserAgent(loginUser);
119
+        refreshToken(loginUser);
120
+
121
+        Map<String, Object> claims = new HashMap<>();
122
+        claims.put(Constants.LOGIN_USER_KEY, token);
123
+        claims.put(Constants.JWT_USERNAME, loginUser.getUsername());
124
+        return createToken(claims);
125
+    }
126
+
127
+    /**
128
+     * 验证令牌有效期,相差不足20分钟,自动刷新缓存
129
+     * 
130
+     * @param loginUser 登录信息
131
+     * @return 令牌
132
+     */
133
+    public void verifyToken(LoginUser loginUser)
134
+    {
135
+        long expireTime = loginUser.getExpireTime();
136
+        long currentTime = System.currentTimeMillis();
137
+        if (expireTime - currentTime <= MILLIS_MINUTE_TWENTY)
138
+        {
139
+            refreshToken(loginUser);
140
+        }
141
+    }
142
+
143
+    /**
144
+     * 刷新令牌有效期
145
+     * 
146
+     * @param loginUser 登录信息
147
+     */
148
+    public void refreshToken(LoginUser loginUser)
149
+    {
150
+        loginUser.setLoginTime(System.currentTimeMillis());
151
+        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
152
+        // 根据uuid将loginUser缓存
153
+        String userKey = getTokenKey(loginUser.getToken());
154
+        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
155
+    }
156
+
157
+    /**
158
+     * 设置用户代理信息
159
+     * 
160
+     * @param loginUser 登录信息
161
+     */
162
+    public void setUserAgent(LoginUser loginUser)
163
+    {
164
+        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
165
+        String ip = IpUtils.getIpAddr();
166
+        loginUser.setIpaddr(ip);
167
+        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
168
+        loginUser.setBrowser(userAgent.getBrowser().getName());
169
+        loginUser.setOs(userAgent.getOperatingSystem().getName());
170
+    }
171
+
172
+    /**
173
+     * 从数据声明生成令牌
174
+     *
175
+     * @param claims 数据声明
176
+     * @return 令牌
177
+     */
178
+    private String createToken(Map<String, Object> claims)
179
+    {
180
+        String token = Jwts.builder()
181
+                .setClaims(claims)
182
+                .signWith(SignatureAlgorithm.HS512, secret).compact();
183
+        return token;
184
+    }
185
+
186
+    /**
187
+     * 从令牌中获取数据声明
188
+     *
189
+     * @param token 令牌
190
+     * @return 数据声明
191
+     */
192
+    private Claims parseToken(String token)
193
+    {
194
+        return Jwts.parser()
195
+                .setSigningKey(secret)
196
+                .parseClaimsJws(token)
197
+                .getBody();
198
+    }
199
+
200
+    /**
201
+     * 从令牌中获取用户名
202
+     *
203
+     * @param token 令牌
204
+     * @return 用户名
205
+     */
206
+    public String getUsernameFromToken(String token)
207
+    {
208
+        Claims claims = parseToken(token);
209
+        return claims.getSubject();
210
+    }
211
+
212
+    /**
213
+     * 获取请求token
214
+     *
215
+     * @param request
216
+     * @return token
217
+     */
218
+    private String getToken(HttpServletRequest request)
219
+    {
220
+        String token = request.getHeader(header);
221
+        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
222
+        {
223
+            token = token.replace(Constants.TOKEN_PREFIX, "");
224
+        }
225
+        return token;
226
+    }
227
+
228
+    private String getTokenKey(String uuid)
229
+    {
230
+        return CacheConstants.LOGIN_TOKEN_KEY + uuid;
231
+    }
232
+}

+ 66 - 0
airport-framework/src/main/java/com/sundot/airport/framework/web/service/UserDetailsServiceImpl.java

@@ -0,0 +1,66 @@
1
+package com.sundot.airport.framework.web.service;
2
+
3
+import org.slf4j.Logger;
4
+import org.slf4j.LoggerFactory;
5
+import org.springframework.beans.factory.annotation.Autowired;
6
+import org.springframework.security.core.userdetails.UserDetails;
7
+import org.springframework.security.core.userdetails.UserDetailsService;
8
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
9
+import org.springframework.stereotype.Service;
10
+import com.sundot.airport.common.core.domain.entity.SysUser;
11
+import com.sundot.airport.common.core.domain.model.LoginUser;
12
+import com.sundot.airport.common.enums.UserStatus;
13
+import com.sundot.airport.common.exception.ServiceException;
14
+import com.sundot.airport.common.utils.MessageUtils;
15
+import com.sundot.airport.common.utils.StringUtils;
16
+import com.sundot.airport.system.service.ISysUserService;
17
+
18
+/**
19
+ * 用户验证处理
20
+ *
21
+ * @author ruoyi
22
+ */
23
+@Service
24
+public class UserDetailsServiceImpl implements UserDetailsService
25
+{
26
+    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
27
+
28
+    @Autowired
29
+    private ISysUserService userService;
30
+    
31
+    @Autowired
32
+    private SysPasswordService passwordService;
33
+
34
+    @Autowired
35
+    private SysPermissionService permissionService;
36
+
37
+    @Override
38
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
39
+    {
40
+        SysUser user = userService.selectUserByUserName(username);
41
+        if (StringUtils.isNull(user))
42
+        {
43
+            log.info("登录用户:{} 不存在.", username);
44
+            throw new ServiceException(MessageUtils.message("user.not.exists"));
45
+        }
46
+        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
47
+        {
48
+            log.info("登录用户:{} 已被删除.", username);
49
+            throw new ServiceException(MessageUtils.message("user.password.delete"));
50
+        }
51
+        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
52
+        {
53
+            log.info("登录用户:{} 已被停用.", username);
54
+            throw new ServiceException(MessageUtils.message("user.blocked"));
55
+        }
56
+
57
+        passwordService.validate(user);
58
+
59
+        return createLoginUser(user);
60
+    }
61
+
62
+    public UserDetails createLoginUser(SysUser user)
63
+    {
64
+        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
65
+    }
66
+}

+ 40 - 0
airport-generator/pom.xml

@@ -0,0 +1,40 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <parent>
6
+        <artifactId>airport</artifactId>
7
+        <groupId>com.sundot.airport</groupId>
8
+        <version>3.9.0</version>
9
+    </parent>
10
+    <modelVersion>4.0.0</modelVersion>
11
+
12
+    <artifactId>airport-generator</artifactId>
13
+
14
+    <description>
15
+        generator代码生成
16
+    </description>
17
+
18
+    <dependencies>
19
+
20
+        <!-- velocity代码生成使用模板 -->
21
+        <dependency>
22
+            <groupId>org.apache.velocity</groupId>
23
+            <artifactId>velocity-engine-core</artifactId>
24
+        </dependency>
25
+
26
+        <!-- 通用工具-->
27
+        <dependency>
28
+            <groupId>com.sundot.airport</groupId>
29
+            <artifactId>airport-common</artifactId>
30
+        </dependency>
31
+
32
+        <!-- 阿里数据库连接池 -->
33
+        <dependency>
34
+            <groupId>com.alibaba</groupId>
35
+            <artifactId>druid-spring-boot-starter</artifactId>
36
+        </dependency>
37
+
38
+    </dependencies>
39
+
40
+</project>

+ 87 - 0
airport-generator/src/main/java/com/sundot/airport/generator/config/GenConfig.java

@@ -0,0 +1,87 @@
1
+package com.sundot.airport.generator.config;
2
+
3
+import org.springframework.beans.factory.annotation.Value;
4
+import org.springframework.boot.context.properties.ConfigurationProperties;
5
+import org.springframework.context.annotation.PropertySource;
6
+import org.springframework.stereotype.Component;
7
+
8
+/**
9
+ * 读取代码生成相关配置
10
+ * 
11
+ * @author ruoyi
12
+ */
13
+@Component
14
+@ConfigurationProperties(prefix = "gen")
15
+@PropertySource(value = { "classpath:generator.yml" })
16
+public class GenConfig
17
+{
18
+    /** 作者 */
19
+    public static String author;
20
+
21
+    /** 生成包路径 */
22
+    public static String packageName;
23
+
24
+    /** 自动去除表前缀 */
25
+    public static boolean autoRemovePre;
26
+
27
+    /** 表前缀 */
28
+    public static String tablePrefix;
29
+
30
+    /** 是否允许生成文件覆盖到本地(自定义路径) */
31
+    public static boolean allowOverwrite;
32
+
33
+    public static String getAuthor()
34
+    {
35
+        return author;
36
+    }
37
+
38
+    @Value("${author}")
39
+    public void setAuthor(String author)
40
+    {
41
+        GenConfig.author = author;
42
+    }
43
+
44
+    public static String getPackageName()
45
+    {
46
+        return packageName;
47
+    }
48
+
49
+    @Value("${packageName}")
50
+    public void setPackageName(String packageName)
51
+    {
52
+        GenConfig.packageName = packageName;
53
+    }
54
+
55
+    public static boolean getAutoRemovePre()
56
+    {
57
+        return autoRemovePre;
58
+    }
59
+
60
+    @Value("${autoRemovePre}")
61
+    public void setAutoRemovePre(boolean autoRemovePre)
62
+    {
63
+        GenConfig.autoRemovePre = autoRemovePre;
64
+    }
65
+
66
+    public static String getTablePrefix()
67
+    {
68
+        return tablePrefix;
69
+    }
70
+
71
+    @Value("${tablePrefix}")
72
+    public void setTablePrefix(String tablePrefix)
73
+    {
74
+        GenConfig.tablePrefix = tablePrefix;
75
+    }
76
+
77
+    public static boolean isAllowOverwrite()
78
+    {
79
+        return allowOverwrite;
80
+    }
81
+
82
+    @Value("${allowOverwrite}")
83
+    public void setAllowOverwrite(boolean allowOverwrite)
84
+    {
85
+        GenConfig.allowOverwrite = allowOverwrite;
86
+    }
87
+}

+ 263 - 0
airport-generator/src/main/java/com/sundot/airport/generator/controller/GenController.java

@@ -0,0 +1,263 @@
1
+package com.sundot.airport.generator.controller;
2
+
3
+import java.io.IOException;
4
+import java.util.ArrayList;
5
+import java.util.HashMap;
6
+import java.util.List;
7
+import java.util.Map;
8
+import javax.servlet.http.HttpServletResponse;
9
+import org.apache.commons.io.IOUtils;
10
+import org.springframework.beans.factory.annotation.Autowired;
11
+import org.springframework.security.access.prepost.PreAuthorize;
12
+import org.springframework.validation.annotation.Validated;
13
+import org.springframework.web.bind.annotation.DeleteMapping;
14
+import org.springframework.web.bind.annotation.GetMapping;
15
+import org.springframework.web.bind.annotation.PathVariable;
16
+import org.springframework.web.bind.annotation.PostMapping;
17
+import org.springframework.web.bind.annotation.PutMapping;
18
+import org.springframework.web.bind.annotation.RequestBody;
19
+import org.springframework.web.bind.annotation.RequestMapping;
20
+import org.springframework.web.bind.annotation.RestController;
21
+import com.alibaba.druid.DbType;
22
+import com.alibaba.druid.sql.SQLUtils;
23
+import com.alibaba.druid.sql.ast.SQLStatement;
24
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
25
+import com.sundot.airport.common.annotation.Log;
26
+import com.sundot.airport.common.core.controller.BaseController;
27
+import com.sundot.airport.common.core.domain.AjaxResult;
28
+import com.sundot.airport.common.core.page.TableDataInfo;
29
+import com.sundot.airport.common.core.text.Convert;
30
+import com.sundot.airport.common.enums.BusinessType;
31
+import com.sundot.airport.common.utils.SecurityUtils;
32
+import com.sundot.airport.common.utils.sql.SqlUtil;
33
+import com.sundot.airport.generator.config.GenConfig;
34
+import com.sundot.airport.generator.domain.GenTable;
35
+import com.sundot.airport.generator.domain.GenTableColumn;
36
+import com.sundot.airport.generator.service.IGenTableColumnService;
37
+import com.sundot.airport.generator.service.IGenTableService;
38
+
39
+/**
40
+ * 代码生成 操作处理
41
+ * 
42
+ * @author ruoyi
43
+ */
44
+@RestController
45
+@RequestMapping("/tool/gen")
46
+public class GenController extends BaseController
47
+{
48
+    @Autowired
49
+    private IGenTableService genTableService;
50
+
51
+    @Autowired
52
+    private IGenTableColumnService genTableColumnService;
53
+
54
+    /**
55
+     * 查询代码生成列表
56
+     */
57
+    @PreAuthorize("@ss.hasPermi('tool:gen:list')")
58
+    @GetMapping("/list")
59
+    public TableDataInfo genList(GenTable genTable)
60
+    {
61
+        startPage();
62
+        List<GenTable> list = genTableService.selectGenTableList(genTable);
63
+        return getDataTable(list);
64
+    }
65
+
66
+    /**
67
+     * 获取代码生成信息
68
+     */
69
+    @PreAuthorize("@ss.hasPermi('tool:gen:query')")
70
+    @GetMapping(value = "/{tableId}")
71
+    public AjaxResult getInfo(@PathVariable Long tableId)
72
+    {
73
+        GenTable table = genTableService.selectGenTableById(tableId);
74
+        List<GenTable> tables = genTableService.selectGenTableAll();
75
+        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
76
+        Map<String, Object> map = new HashMap<String, Object>();
77
+        map.put("info", table);
78
+        map.put("rows", list);
79
+        map.put("tables", tables);
80
+        return success(map);
81
+    }
82
+
83
+    /**
84
+     * 查询数据库列表
85
+     */
86
+    @PreAuthorize("@ss.hasPermi('tool:gen:list')")
87
+    @GetMapping("/db/list")
88
+    public TableDataInfo dataList(GenTable genTable)
89
+    {
90
+        startPage();
91
+        List<GenTable> list = genTableService.selectDbTableList(genTable);
92
+        return getDataTable(list);
93
+    }
94
+
95
+    /**
96
+     * 查询数据表字段列表
97
+     */
98
+    @PreAuthorize("@ss.hasPermi('tool:gen:list')")
99
+    @GetMapping(value = "/column/{tableId}")
100
+    public TableDataInfo columnList(Long tableId)
101
+    {
102
+        TableDataInfo dataInfo = new TableDataInfo();
103
+        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
104
+        dataInfo.setRows(list);
105
+        dataInfo.setTotal(list.size());
106
+        return dataInfo;
107
+    }
108
+
109
+    /**
110
+     * 导入表结构(保存)
111
+     */
112
+    @PreAuthorize("@ss.hasPermi('tool:gen:import')")
113
+    @Log(title = "代码生成", businessType = BusinessType.IMPORT)
114
+    @PostMapping("/importTable")
115
+    public AjaxResult importTableSave(String tables)
116
+    {
117
+        String[] tableNames = Convert.toStrArray(tables);
118
+        // 查询表信息
119
+        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
120
+        genTableService.importGenTable(tableList, SecurityUtils.getUsername());
121
+        return success();
122
+    }
123
+
124
+    /**
125
+     * 创建表结构(保存)
126
+     */
127
+    @PreAuthorize("@ss.hasRole('admin')")
128
+    @Log(title = "创建表", businessType = BusinessType.OTHER)
129
+    @PostMapping("/createTable")
130
+    public AjaxResult createTableSave(String sql)
131
+    {
132
+        try
133
+        {
134
+            SqlUtil.filterKeyword(sql);
135
+            List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
136
+            List<String> tableNames = new ArrayList<>();
137
+            for (SQLStatement sqlStatement : sqlStatements)
138
+            {
139
+                if (sqlStatement instanceof MySqlCreateTableStatement)
140
+                {
141
+                    MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
142
+                    if (genTableService.createTable(createTableStatement.toString()))
143
+                    {
144
+                        String tableName = createTableStatement.getTableName().replaceAll("`", "");
145
+                        tableNames.add(tableName);
146
+                    }
147
+                }
148
+            }
149
+            List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
150
+            String operName = SecurityUtils.getUsername();
151
+            genTableService.importGenTable(tableList, operName);
152
+            return AjaxResult.success();
153
+        }
154
+        catch (Exception e)
155
+        {
156
+            logger.error(e.getMessage(), e);
157
+            return AjaxResult.error("创建表结构异常");
158
+        }
159
+    }
160
+
161
+    /**
162
+     * 修改保存代码生成业务
163
+     */
164
+    @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
165
+    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
166
+    @PutMapping
167
+    public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
168
+    {
169
+        genTableService.validateEdit(genTable);
170
+        genTableService.updateGenTable(genTable);
171
+        return success();
172
+    }
173
+
174
+    /**
175
+     * 删除代码生成
176
+     */
177
+    @PreAuthorize("@ss.hasPermi('tool:gen:remove')")
178
+    @Log(title = "代码生成", businessType = BusinessType.DELETE)
179
+    @DeleteMapping("/{tableIds}")
180
+    public AjaxResult remove(@PathVariable Long[] tableIds)
181
+    {
182
+        genTableService.deleteGenTableByIds(tableIds);
183
+        return success();
184
+    }
185
+
186
+    /**
187
+     * 预览代码
188
+     */
189
+    @PreAuthorize("@ss.hasPermi('tool:gen:preview')")
190
+    @GetMapping("/preview/{tableId}")
191
+    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
192
+    {
193
+        Map<String, String> dataMap = genTableService.previewCode(tableId);
194
+        return success(dataMap);
195
+    }
196
+
197
+    /**
198
+     * 生成代码(下载方式)
199
+     */
200
+    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
201
+    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
202
+    @GetMapping("/download/{tableName}")
203
+    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
204
+    {
205
+        byte[] data = genTableService.downloadCode(tableName);
206
+        genCode(response, data);
207
+    }
208
+
209
+    /**
210
+     * 生成代码(自定义路径)
211
+     */
212
+    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
213
+    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
214
+    @GetMapping("/genCode/{tableName}")
215
+    public AjaxResult genCode(@PathVariable("tableName") String tableName)
216
+    {
217
+        if (!GenConfig.isAllowOverwrite())
218
+        {
219
+            return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
220
+        }
221
+        genTableService.generatorCode(tableName);
222
+        return success();
223
+    }
224
+
225
+    /**
226
+     * 同步数据库
227
+     */
228
+    @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
229
+    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
230
+    @GetMapping("/synchDb/{tableName}")
231
+    public AjaxResult synchDb(@PathVariable("tableName") String tableName)
232
+    {
233
+        genTableService.synchDb(tableName);
234
+        return success();
235
+    }
236
+
237
+    /**
238
+     * 批量生成代码
239
+     */
240
+    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
241
+    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
242
+    @GetMapping("/batchGenCode")
243
+    public void batchGenCode(HttpServletResponse response, String tables) throws IOException
244
+    {
245
+        String[] tableNames = Convert.toStrArray(tables);
246
+        byte[] data = genTableService.downloadCode(tableNames);
247
+        genCode(response, data);
248
+    }
249
+
250
+    /**
251
+     * 生成zip文件
252
+     */
253
+    private void genCode(HttpServletResponse response, byte[] data) throws IOException
254
+    {
255
+        response.reset();
256
+        response.addHeader("Access-Control-Allow-Origin", "*");
257
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
258
+        response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
259
+        response.addHeader("Content-Length", "" + data.length);
260
+        response.setContentType("application/octet-stream; charset=UTF-8");
261
+        IOUtils.write(data, response.getOutputStream());
262
+    }
263
+}

+ 385 - 0
airport-generator/src/main/java/com/sundot/airport/generator/domain/GenTable.java

@@ -0,0 +1,385 @@
1
+package com.sundot.airport.generator.domain;
2
+
3
+import java.util.List;
4
+import javax.validation.Valid;
5
+import javax.validation.constraints.NotBlank;
6
+import org.apache.commons.lang3.ArrayUtils;
7
+import com.sundot.airport.common.constant.GenConstants;
8
+import com.sundot.airport.common.core.domain.BaseEntity;
9
+import com.sundot.airport.common.utils.StringUtils;
10
+
11
+/**
12
+ * 业务表 gen_table
13
+ * 
14
+ * @author ruoyi
15
+ */
16
+public class GenTable extends BaseEntity
17
+{
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /** 编号 */
21
+    private Long tableId;
22
+
23
+    /** 表名称 */
24
+    @NotBlank(message = "表名称不能为空")
25
+    private String tableName;
26
+
27
+    /** 表描述 */
28
+    @NotBlank(message = "表描述不能为空")
29
+    private String tableComment;
30
+
31
+    /** 关联父表的表名 */
32
+    private String subTableName;
33
+
34
+    /** 本表关联父表的外键名 */
35
+    private String subTableFkName;
36
+
37
+    /** 实体类名称(首字母大写) */
38
+    @NotBlank(message = "实体类名称不能为空")
39
+    private String className;
40
+
41
+    /** 使用的模板(crud单表操作 tree树表操作 sub主子表操作) */
42
+    private String tplCategory;
43
+
44
+    /** 前端类型(element-ui模版 element-plus模版) */
45
+    private String tplWebType;
46
+
47
+    /** 生成包路径 */
48
+    @NotBlank(message = "生成包路径不能为空")
49
+    private String packageName;
50
+
51
+    /** 生成模块名 */
52
+    @NotBlank(message = "生成模块名不能为空")
53
+    private String moduleName;
54
+
55
+    /** 生成业务名 */
56
+    @NotBlank(message = "生成业务名不能为空")
57
+    private String businessName;
58
+
59
+    /** 生成功能名 */
60
+    @NotBlank(message = "生成功能名不能为空")
61
+    private String functionName;
62
+
63
+    /** 生成作者 */
64
+    @NotBlank(message = "作者不能为空")
65
+    private String functionAuthor;
66
+
67
+    /** 生成代码方式(0zip压缩包 1自定义路径) */
68
+    private String genType;
69
+
70
+    /** 生成路径(不填默认项目路径) */
71
+    private String genPath;
72
+
73
+    /** 主键信息 */
74
+    private GenTableColumn pkColumn;
75
+
76
+    /** 子表信息 */
77
+    private GenTable subTable;
78
+
79
+    /** 表列信息 */
80
+    @Valid
81
+    private List<GenTableColumn> columns;
82
+
83
+    /** 其它生成选项 */
84
+    private String options;
85
+
86
+    /** 树编码字段 */
87
+    private String treeCode;
88
+
89
+    /** 树父编码字段 */
90
+    private String treeParentCode;
91
+
92
+    /** 树名称字段 */
93
+    private String treeName;
94
+
95
+    /** 上级菜单ID字段 */
96
+    private Long parentMenuId;
97
+
98
+    /** 上级菜单名称字段 */
99
+    private String parentMenuName;
100
+
101
+    public Long getTableId()
102
+    {
103
+        return tableId;
104
+    }
105
+
106
+    public void setTableId(Long tableId)
107
+    {
108
+        this.tableId = tableId;
109
+    }
110
+
111
+    public String getTableName()
112
+    {
113
+        return tableName;
114
+    }
115
+
116
+    public void setTableName(String tableName)
117
+    {
118
+        this.tableName = tableName;
119
+    }
120
+
121
+    public String getTableComment()
122
+    {
123
+        return tableComment;
124
+    }
125
+
126
+    public void setTableComment(String tableComment)
127
+    {
128
+        this.tableComment = tableComment;
129
+    }
130
+
131
+    public String getSubTableName()
132
+    {
133
+        return subTableName;
134
+    }
135
+
136
+    public void setSubTableName(String subTableName)
137
+    {
138
+        this.subTableName = subTableName;
139
+    }
140
+
141
+    public String getSubTableFkName()
142
+    {
143
+        return subTableFkName;
144
+    }
145
+
146
+    public void setSubTableFkName(String subTableFkName)
147
+    {
148
+        this.subTableFkName = subTableFkName;
149
+    }
150
+
151
+    public String getClassName()
152
+    {
153
+        return className;
154
+    }
155
+
156
+    public void setClassName(String className)
157
+    {
158
+        this.className = className;
159
+    }
160
+
161
+    public String getTplCategory()
162
+    {
163
+        return tplCategory;
164
+    }
165
+
166
+    public void setTplCategory(String tplCategory)
167
+    {
168
+        this.tplCategory = tplCategory;
169
+    }
170
+
171
+    public String getTplWebType()
172
+    {
173
+        return tplWebType;
174
+    }
175
+
176
+    public void setTplWebType(String tplWebType)
177
+    {
178
+        this.tplWebType = tplWebType;
179
+    }
180
+
181
+    public String getPackageName()
182
+    {
183
+        return packageName;
184
+    }
185
+
186
+    public void setPackageName(String packageName)
187
+    {
188
+        this.packageName = packageName;
189
+    }
190
+
191
+    public String getModuleName()
192
+    {
193
+        return moduleName;
194
+    }
195
+
196
+    public void setModuleName(String moduleName)
197
+    {
198
+        this.moduleName = moduleName;
199
+    }
200
+
201
+    public String getBusinessName()
202
+    {
203
+        return businessName;
204
+    }
205
+
206
+    public void setBusinessName(String businessName)
207
+    {
208
+        this.businessName = businessName;
209
+    }
210
+
211
+    public String getFunctionName()
212
+    {
213
+        return functionName;
214
+    }
215
+
216
+    public void setFunctionName(String functionName)
217
+    {
218
+        this.functionName = functionName;
219
+    }
220
+
221
+    public String getFunctionAuthor()
222
+    {
223
+        return functionAuthor;
224
+    }
225
+
226
+    public void setFunctionAuthor(String functionAuthor)
227
+    {
228
+        this.functionAuthor = functionAuthor;
229
+    }
230
+
231
+    public String getGenType()
232
+    {
233
+        return genType;
234
+    }
235
+
236
+    public void setGenType(String genType)
237
+    {
238
+        this.genType = genType;
239
+    }
240
+
241
+    public String getGenPath()
242
+    {
243
+        return genPath;
244
+    }
245
+
246
+    public void setGenPath(String genPath)
247
+    {
248
+        this.genPath = genPath;
249
+    }
250
+
251
+    public GenTableColumn getPkColumn()
252
+    {
253
+        return pkColumn;
254
+    }
255
+
256
+    public void setPkColumn(GenTableColumn pkColumn)
257
+    {
258
+        this.pkColumn = pkColumn;
259
+    }
260
+
261
+    public GenTable getSubTable()
262
+    {
263
+        return subTable;
264
+    }
265
+
266
+    public void setSubTable(GenTable subTable)
267
+    {
268
+        this.subTable = subTable;
269
+    }
270
+
271
+    public List<GenTableColumn> getColumns()
272
+    {
273
+        return columns;
274
+    }
275
+
276
+    public void setColumns(List<GenTableColumn> columns)
277
+    {
278
+        this.columns = columns;
279
+    }
280
+
281
+    public String getOptions()
282
+    {
283
+        return options;
284
+    }
285
+
286
+    public void setOptions(String options)
287
+    {
288
+        this.options = options;
289
+    }
290
+
291
+    public String getTreeCode()
292
+    {
293
+        return treeCode;
294
+    }
295
+
296
+    public void setTreeCode(String treeCode)
297
+    {
298
+        this.treeCode = treeCode;
299
+    }
300
+
301
+    public String getTreeParentCode()
302
+    {
303
+        return treeParentCode;
304
+    }
305
+
306
+    public void setTreeParentCode(String treeParentCode)
307
+    {
308
+        this.treeParentCode = treeParentCode;
309
+    }
310
+
311
+    public String getTreeName()
312
+    {
313
+        return treeName;
314
+    }
315
+
316
+    public void setTreeName(String treeName)
317
+    {
318
+        this.treeName = treeName;
319
+    }
320
+
321
+    public Long getParentMenuId()
322
+    {
323
+        return parentMenuId;
324
+    }
325
+
326
+    public void setParentMenuId(Long parentMenuId)
327
+    {
328
+        this.parentMenuId = parentMenuId;
329
+    }
330
+
331
+    public String getParentMenuName()
332
+    {
333
+        return parentMenuName;
334
+    }
335
+
336
+    public void setParentMenuName(String parentMenuName)
337
+    {
338
+        this.parentMenuName = parentMenuName;
339
+    }
340
+
341
+    public boolean isSub()
342
+    {
343
+        return isSub(this.tplCategory);
344
+    }
345
+
346
+    public static boolean isSub(String tplCategory)
347
+    {
348
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory);
349
+    }
350
+
351
+    public boolean isTree()
352
+    {
353
+        return isTree(this.tplCategory);
354
+    }
355
+
356
+    public static boolean isTree(String tplCategory)
357
+    {
358
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
359
+    }
360
+
361
+    public boolean isCrud()
362
+    {
363
+        return isCrud(this.tplCategory);
364
+    }
365
+
366
+    public static boolean isCrud(String tplCategory)
367
+    {
368
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
369
+    }
370
+
371
+    public boolean isSuperColumn(String javaField)
372
+    {
373
+        return isSuperColumn(this.tplCategory, javaField);
374
+    }
375
+
376
+    public static boolean isSuperColumn(String tplCategory, String javaField)
377
+    {
378
+        if (isTree(tplCategory))
379
+        {
380
+            return StringUtils.equalsAnyIgnoreCase(javaField,
381
+                    ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
382
+        }
383
+        return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
384
+    }
385
+}

+ 373 - 0
airport-generator/src/main/java/com/sundot/airport/generator/domain/GenTableColumn.java

@@ -0,0 +1,373 @@
1
+package com.sundot.airport.generator.domain;
2
+
3
+import javax.validation.constraints.NotBlank;
4
+import com.sundot.airport.common.core.domain.BaseEntity;
5
+import com.sundot.airport.common.utils.StringUtils;
6
+
7
+/**
8
+ * 代码生成业务字段表 gen_table_column
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+public class GenTableColumn extends BaseEntity
13
+{
14
+    private static final long serialVersionUID = 1L;
15
+
16
+    /** 编号 */
17
+    private Long columnId;
18
+
19
+    /** 归属表编号 */
20
+    private Long tableId;
21
+
22
+    /** 列名称 */
23
+    private String columnName;
24
+
25
+    /** 列描述 */
26
+    private String columnComment;
27
+
28
+    /** 列类型 */
29
+    private String columnType;
30
+
31
+    /** JAVA类型 */
32
+    private String javaType;
33
+
34
+    /** JAVA字段名 */
35
+    @NotBlank(message = "Java属性不能为空")
36
+    private String javaField;
37
+
38
+    /** 是否主键(1是) */
39
+    private String isPk;
40
+
41
+    /** 是否自增(1是) */
42
+    private String isIncrement;
43
+
44
+    /** 是否必填(1是) */
45
+    private String isRequired;
46
+
47
+    /** 是否为插入字段(1是) */
48
+    private String isInsert;
49
+
50
+    /** 是否编辑字段(1是) */
51
+    private String isEdit;
52
+
53
+    /** 是否列表字段(1是) */
54
+    private String isList;
55
+
56
+    /** 是否查询字段(1是) */
57
+    private String isQuery;
58
+
59
+    /** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
60
+    private String queryType;
61
+
62
+    /** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、image图片上传控件、upload文件上传控件、editor富文本控件) */
63
+    private String htmlType;
64
+
65
+    /** 字典类型 */
66
+    private String dictType;
67
+
68
+    /** 排序 */
69
+    private Integer sort;
70
+
71
+    public void setColumnId(Long columnId)
72
+    {
73
+        this.columnId = columnId;
74
+    }
75
+
76
+    public Long getColumnId()
77
+    {
78
+        return columnId;
79
+    }
80
+
81
+    public void setTableId(Long tableId)
82
+    {
83
+        this.tableId = tableId;
84
+    }
85
+
86
+    public Long getTableId()
87
+    {
88
+        return tableId;
89
+    }
90
+
91
+    public void setColumnName(String columnName)
92
+    {
93
+        this.columnName = columnName;
94
+    }
95
+
96
+    public String getColumnName()
97
+    {
98
+        return columnName;
99
+    }
100
+
101
+    public void setColumnComment(String columnComment)
102
+    {
103
+        this.columnComment = columnComment;
104
+    }
105
+
106
+    public String getColumnComment()
107
+    {
108
+        return columnComment;
109
+    }
110
+
111
+    public void setColumnType(String columnType)
112
+    {
113
+        this.columnType = columnType;
114
+    }
115
+
116
+    public String getColumnType()
117
+    {
118
+        return columnType;
119
+    }
120
+
121
+    public void setJavaType(String javaType)
122
+    {
123
+        this.javaType = javaType;
124
+    }
125
+
126
+    public String getJavaType()
127
+    {
128
+        return javaType;
129
+    }
130
+
131
+    public void setJavaField(String javaField)
132
+    {
133
+        this.javaField = javaField;
134
+    }
135
+
136
+    public String getJavaField()
137
+    {
138
+        return javaField;
139
+    }
140
+
141
+    public String getCapJavaField()
142
+    {
143
+        return StringUtils.capitalize(javaField);
144
+    }
145
+
146
+    public void setIsPk(String isPk)
147
+    {
148
+        this.isPk = isPk;
149
+    }
150
+
151
+    public String getIsPk()
152
+    {
153
+        return isPk;
154
+    }
155
+
156
+    public boolean isPk()
157
+    {
158
+        return isPk(this.isPk);
159
+    }
160
+
161
+    public boolean isPk(String isPk)
162
+    {
163
+        return isPk != null && StringUtils.equals("1", isPk);
164
+    }
165
+
166
+    public String getIsIncrement()
167
+    {
168
+        return isIncrement;
169
+    }
170
+
171
+    public void setIsIncrement(String isIncrement)
172
+    {
173
+        this.isIncrement = isIncrement;
174
+    }
175
+
176
+    public boolean isIncrement()
177
+    {
178
+        return isIncrement(this.isIncrement);
179
+    }
180
+
181
+    public boolean isIncrement(String isIncrement)
182
+    {
183
+        return isIncrement != null && StringUtils.equals("1", isIncrement);
184
+    }
185
+
186
+    public void setIsRequired(String isRequired)
187
+    {
188
+        this.isRequired = isRequired;
189
+    }
190
+
191
+    public String getIsRequired()
192
+    {
193
+        return isRequired;
194
+    }
195
+
196
+    public boolean isRequired()
197
+    {
198
+        return isRequired(this.isRequired);
199
+    }
200
+
201
+    public boolean isRequired(String isRequired)
202
+    {
203
+        return isRequired != null && StringUtils.equals("1", isRequired);
204
+    }
205
+
206
+    public void setIsInsert(String isInsert)
207
+    {
208
+        this.isInsert = isInsert;
209
+    }
210
+
211
+    public String getIsInsert()
212
+    {
213
+        return isInsert;
214
+    }
215
+
216
+    public boolean isInsert()
217
+    {
218
+        return isInsert(this.isInsert);
219
+    }
220
+
221
+    public boolean isInsert(String isInsert)
222
+    {
223
+        return isInsert != null && StringUtils.equals("1", isInsert);
224
+    }
225
+
226
+    public void setIsEdit(String isEdit)
227
+    {
228
+        this.isEdit = isEdit;
229
+    }
230
+
231
+    public String getIsEdit()
232
+    {
233
+        return isEdit;
234
+    }
235
+
236
+    public boolean isEdit()
237
+    {
238
+        return isInsert(this.isEdit);
239
+    }
240
+
241
+    public boolean isEdit(String isEdit)
242
+    {
243
+        return isEdit != null && StringUtils.equals("1", isEdit);
244
+    }
245
+
246
+    public void setIsList(String isList)
247
+    {
248
+        this.isList = isList;
249
+    }
250
+
251
+    public String getIsList()
252
+    {
253
+        return isList;
254
+    }
255
+
256
+    public boolean isList()
257
+    {
258
+        return isList(this.isList);
259
+    }
260
+
261
+    public boolean isList(String isList)
262
+    {
263
+        return isList != null && StringUtils.equals("1", isList);
264
+    }
265
+
266
+    public void setIsQuery(String isQuery)
267
+    {
268
+        this.isQuery = isQuery;
269
+    }
270
+
271
+    public String getIsQuery()
272
+    {
273
+        return isQuery;
274
+    }
275
+
276
+    public boolean isQuery()
277
+    {
278
+        return isQuery(this.isQuery);
279
+    }
280
+
281
+    public boolean isQuery(String isQuery)
282
+    {
283
+        return isQuery != null && StringUtils.equals("1", isQuery);
284
+    }
285
+
286
+    public void setQueryType(String queryType)
287
+    {
288
+        this.queryType = queryType;
289
+    }
290
+
291
+    public String getQueryType()
292
+    {
293
+        return queryType;
294
+    }
295
+
296
+    public String getHtmlType()
297
+    {
298
+        return htmlType;
299
+    }
300
+
301
+    public void setHtmlType(String htmlType)
302
+    {
303
+        this.htmlType = htmlType;
304
+    }
305
+
306
+    public void setDictType(String dictType)
307
+    {
308
+        this.dictType = dictType;
309
+    }
310
+
311
+    public String getDictType()
312
+    {
313
+        return dictType;
314
+    }
315
+
316
+    public void setSort(Integer sort)
317
+    {
318
+        this.sort = sort;
319
+    }
320
+
321
+    public Integer getSort()
322
+    {
323
+        return sort;
324
+    }
325
+
326
+    public boolean isSuperColumn()
327
+    {
328
+        return isSuperColumn(this.javaField);
329
+    }
330
+
331
+    public static boolean isSuperColumn(String javaField)
332
+    {
333
+        return StringUtils.equalsAnyIgnoreCase(javaField,
334
+                // BaseEntity
335
+                "createBy", "createTime", "updateBy", "updateTime", "remark",
336
+                // TreeEntity
337
+                "parentName", "parentId", "orderNum", "ancestors");
338
+    }
339
+
340
+    public boolean isUsableColumn()
341
+    {
342
+        return isUsableColumn(javaField);
343
+    }
344
+
345
+    public static boolean isUsableColumn(String javaField)
346
+    {
347
+        // isSuperColumn()中的名单用于避免生成多余Domain属性,若某些属性在生成页面时需要用到不能忽略,则放在此处白名单
348
+        return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
349
+    }
350
+
351
+    public String readConverterExp()
352
+    {
353
+        String remarks = StringUtils.substringBetween(this.columnComment, "(", ")");
354
+        StringBuffer sb = new StringBuffer();
355
+        if (StringUtils.isNotEmpty(remarks))
356
+        {
357
+            for (String value : remarks.split(" "))
358
+            {
359
+                if (StringUtils.isNotEmpty(value))
360
+                {
361
+                    Object startStr = value.subSequence(0, 1);
362
+                    String endStr = value.substring(1);
363
+                    sb.append("").append(startStr).append("=").append(endStr).append(",");
364
+                }
365
+            }
366
+            return sb.deleteCharAt(sb.length() - 1).toString();
367
+        }
368
+        else
369
+        {
370
+            return this.columnComment;
371
+        }
372
+    }
373
+}

+ 60 - 0
airport-generator/src/main/java/com/sundot/airport/generator/mapper/GenTableColumnMapper.java

@@ -0,0 +1,60 @@
1
+package com.sundot.airport.generator.mapper;
2
+
3
+import java.util.List;
4
+import com.sundot.airport.generator.domain.GenTableColumn;
5
+
6
+/**
7
+ * 业务字段 数据层
8
+ * 
9
+ * @author ruoyi
10
+ */
11
+public interface GenTableColumnMapper
12
+{
13
+    /**
14
+     * 根据表名称查询列信息
15
+     * 
16
+     * @param tableName 表名称
17
+     * @return 列信息
18
+     */
19
+    public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
20
+
21
+    /**
22
+     * 查询业务字段列表
23
+     * 
24
+     * @param tableId 业务字段编号
25
+     * @return 业务字段集合
26
+     */
27
+    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
28
+
29
+    /**
30
+     * 新增业务字段
31
+     * 
32
+     * @param genTableColumn 业务字段信息
33
+     * @return 结果
34
+     */
35
+    public int insertGenTableColumn(GenTableColumn genTableColumn);
36
+
37
+    /**
38
+     * 修改业务字段
39
+     * 
40
+     * @param genTableColumn 业务字段信息
41
+     * @return 结果
42
+     */
43
+    public int updateGenTableColumn(GenTableColumn genTableColumn);
44
+
45
+    /**
46
+     * 删除业务字段
47
+     * 
48
+     * @param genTableColumns 列数据
49
+     * @return 结果
50
+     */
51
+    public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
52
+
53
+    /**
54
+     * 批量删除业务字段
55
+     * 
56
+     * @param ids 需要删除的数据ID
57
+     * @return 结果
58
+     */
59
+    public int deleteGenTableColumnByIds(Long[] ids);
60
+}

+ 91 - 0
airport-generator/src/main/java/com/sundot/airport/generator/mapper/GenTableMapper.java

@@ -0,0 +1,91 @@
1
+package com.sundot.airport.generator.mapper;
2
+
3
+import java.util.List;
4
+import com.sundot.airport.generator.domain.GenTable;
5
+
6
+/**
7
+ * 业务 数据层
8
+ * 
9
+ * @author ruoyi
10
+ */
11
+public interface GenTableMapper
12
+{
13
+    /**
14
+     * 查询业务列表
15
+     * 
16
+     * @param genTable 业务信息
17
+     * @return 业务集合
18
+     */
19
+    public List<GenTable> selectGenTableList(GenTable genTable);
20
+
21
+    /**
22
+     * 查询据库列表
23
+     * 
24
+     * @param genTable 业务信息
25
+     * @return 数据库表集合
26
+     */
27
+    public List<GenTable> selectDbTableList(GenTable genTable);
28
+
29
+    /**
30
+     * 查询据库列表
31
+     * 
32
+     * @param tableNames 表名称组
33
+     * @return 数据库表集合
34
+     */
35
+    public List<GenTable> selectDbTableListByNames(String[] tableNames);
36
+
37
+    /**
38
+     * 查询所有表信息
39
+     * 
40
+     * @return 表信息集合
41
+     */
42
+    public List<GenTable> selectGenTableAll();
43
+
44
+    /**
45
+     * 查询表ID业务信息
46
+     * 
47
+     * @param id 业务ID
48
+     * @return 业务信息
49
+     */
50
+    public GenTable selectGenTableById(Long id);
51
+
52
+    /**
53
+     * 查询表名称业务信息
54
+     * 
55
+     * @param tableName 表名称
56
+     * @return 业务信息
57
+     */
58
+    public GenTable selectGenTableByName(String tableName);
59
+
60
+    /**
61
+     * 新增业务
62
+     * 
63
+     * @param genTable 业务信息
64
+     * @return 结果
65
+     */
66
+    public int insertGenTable(GenTable genTable);
67
+
68
+    /**
69
+     * 修改业务
70
+     * 
71
+     * @param genTable 业务信息
72
+     * @return 结果
73
+     */
74
+    public int updateGenTable(GenTable genTable);
75
+
76
+    /**
77
+     * 批量删除业务
78
+     * 
79
+     * @param ids 需要删除的数据ID
80
+     * @return 结果
81
+     */
82
+    public int deleteGenTableByIds(Long[] ids);
83
+
84
+    /**
85
+     * 创建表
86
+     *
87
+     * @param sql 表结构
88
+     * @return 结果
89
+     */
90
+    public int createTable(String sql);
91
+}

+ 68 - 0
airport-generator/src/main/java/com/sundot/airport/generator/service/GenTableColumnServiceImpl.java

@@ -0,0 +1,68 @@
1
+package com.sundot.airport.generator.service;
2
+
3
+import java.util.List;
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+import org.springframework.stereotype.Service;
6
+import com.sundot.airport.common.core.text.Convert;
7
+import com.sundot.airport.generator.domain.GenTableColumn;
8
+import com.sundot.airport.generator.mapper.GenTableColumnMapper;
9
+
10
+/**
11
+ * 业务字段 服务层实现
12
+ * 
13
+ * @author ruoyi
14
+ */
15
+@Service
16
+public class GenTableColumnServiceImpl implements IGenTableColumnService 
17
+{
18
+	@Autowired
19
+	private GenTableColumnMapper genTableColumnMapper;
20
+
21
+	/**
22
+     * 查询业务字段列表
23
+     * 
24
+     * @param tableId 业务字段编号
25
+     * @return 业务字段集合
26
+     */
27
+	@Override
28
+	public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId)
29
+	{
30
+	    return genTableColumnMapper.selectGenTableColumnListByTableId(tableId);
31
+	}
32
+	
33
+    /**
34
+     * 新增业务字段
35
+     * 
36
+     * @param genTableColumn 业务字段信息
37
+     * @return 结果
38
+     */
39
+	@Override
40
+	public int insertGenTableColumn(GenTableColumn genTableColumn)
41
+	{
42
+	    return genTableColumnMapper.insertGenTableColumn(genTableColumn);
43
+	}
44
+	
45
+	/**
46
+     * 修改业务字段
47
+     * 
48
+     * @param genTableColumn 业务字段信息
49
+     * @return 结果
50
+     */
51
+	@Override
52
+	public int updateGenTableColumn(GenTableColumn genTableColumn)
53
+	{
54
+	    return genTableColumnMapper.updateGenTableColumn(genTableColumn);
55
+	}
56
+
57
+	/**
58
+     * 删除业务字段对象
59
+     * 
60
+     * @param ids 需要删除的数据ID
61
+     * @return 结果
62
+     */
63
+	@Override
64
+	public int deleteGenTableColumnByIds(String ids)
65
+	{
66
+		return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
67
+	}
68
+}

+ 531 - 0
airport-generator/src/main/java/com/sundot/airport/generator/service/GenTableServiceImpl.java

@@ -0,0 +1,531 @@
1
+package com.sundot.airport.generator.service;
2
+
3
+import java.io.ByteArrayOutputStream;
4
+import java.io.File;
5
+import java.io.IOException;
6
+import java.io.StringWriter;
7
+import java.util.LinkedHashMap;
8
+import java.util.List;
9
+import java.util.Map;
10
+import java.util.function.Function;
11
+import java.util.stream.Collectors;
12
+import java.util.zip.ZipEntry;
13
+import java.util.zip.ZipOutputStream;
14
+import org.apache.commons.io.FileUtils;
15
+import org.apache.commons.io.IOUtils;
16
+import org.apache.velocity.Template;
17
+import org.apache.velocity.VelocityContext;
18
+import org.apache.velocity.app.Velocity;
19
+import org.slf4j.Logger;
20
+import org.slf4j.LoggerFactory;
21
+import org.springframework.beans.factory.annotation.Autowired;
22
+import org.springframework.stereotype.Service;
23
+import org.springframework.transaction.annotation.Transactional;
24
+import com.alibaba.fastjson2.JSON;
25
+import com.alibaba.fastjson2.JSONObject;
26
+import com.sundot.airport.common.constant.Constants;
27
+import com.sundot.airport.common.constant.GenConstants;
28
+import com.sundot.airport.common.core.text.CharsetKit;
29
+import com.sundot.airport.common.exception.ServiceException;
30
+import com.sundot.airport.common.utils.StringUtils;
31
+import com.sundot.airport.generator.domain.GenTable;
32
+import com.sundot.airport.generator.domain.GenTableColumn;
33
+import com.sundot.airport.generator.mapper.GenTableColumnMapper;
34
+import com.sundot.airport.generator.mapper.GenTableMapper;
35
+import com.sundot.airport.generator.util.GenUtils;
36
+import com.sundot.airport.generator.util.VelocityInitializer;
37
+import com.sundot.airport.generator.util.VelocityUtils;
38
+
39
+/**
40
+ * 业务 服务层实现
41
+ * 
42
+ * @author ruoyi
43
+ */
44
+@Service
45
+public class GenTableServiceImpl implements IGenTableService
46
+{
47
+    private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
48
+
49
+    @Autowired
50
+    private GenTableMapper genTableMapper;
51
+
52
+    @Autowired
53
+    private GenTableColumnMapper genTableColumnMapper;
54
+
55
+    /**
56
+     * 查询业务信息
57
+     * 
58
+     * @param id 业务ID
59
+     * @return 业务信息
60
+     */
61
+    @Override
62
+    public GenTable selectGenTableById(Long id)
63
+    {
64
+        GenTable genTable = genTableMapper.selectGenTableById(id);
65
+        setTableFromOptions(genTable);
66
+        return genTable;
67
+    }
68
+
69
+    /**
70
+     * 查询业务列表
71
+     * 
72
+     * @param genTable 业务信息
73
+     * @return 业务集合
74
+     */
75
+    @Override
76
+    public List<GenTable> selectGenTableList(GenTable genTable)
77
+    {
78
+        return genTableMapper.selectGenTableList(genTable);
79
+    }
80
+
81
+    /**
82
+     * 查询据库列表
83
+     * 
84
+     * @param genTable 业务信息
85
+     * @return 数据库表集合
86
+     */
87
+    @Override
88
+    public List<GenTable> selectDbTableList(GenTable genTable)
89
+    {
90
+        return genTableMapper.selectDbTableList(genTable);
91
+    }
92
+
93
+    /**
94
+     * 查询据库列表
95
+     * 
96
+     * @param tableNames 表名称组
97
+     * @return 数据库表集合
98
+     */
99
+    @Override
100
+    public List<GenTable> selectDbTableListByNames(String[] tableNames)
101
+    {
102
+        return genTableMapper.selectDbTableListByNames(tableNames);
103
+    }
104
+
105
+    /**
106
+     * 查询所有表信息
107
+     * 
108
+     * @return 表信息集合
109
+     */
110
+    @Override
111
+    public List<GenTable> selectGenTableAll()
112
+    {
113
+        return genTableMapper.selectGenTableAll();
114
+    }
115
+
116
+    /**
117
+     * 修改业务
118
+     * 
119
+     * @param genTable 业务信息
120
+     * @return 结果
121
+     */
122
+    @Override
123
+    @Transactional
124
+    public void updateGenTable(GenTable genTable)
125
+    {
126
+        String options = JSON.toJSONString(genTable.getParams());
127
+        genTable.setOptions(options);
128
+        int row = genTableMapper.updateGenTable(genTable);
129
+        if (row > 0)
130
+        {
131
+            for (GenTableColumn genTableColumn : genTable.getColumns())
132
+            {
133
+                genTableColumnMapper.updateGenTableColumn(genTableColumn);
134
+            }
135
+        }
136
+    }
137
+
138
+    /**
139
+     * 删除业务对象
140
+     * 
141
+     * @param tableIds 需要删除的数据ID
142
+     * @return 结果
143
+     */
144
+    @Override
145
+    @Transactional
146
+    public void deleteGenTableByIds(Long[] tableIds)
147
+    {
148
+        genTableMapper.deleteGenTableByIds(tableIds);
149
+        genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
150
+    }
151
+
152
+    /**
153
+     * 创建表
154
+     *
155
+     * @param sql 创建表语句
156
+     * @return 结果
157
+     */
158
+    @Override
159
+    public boolean createTable(String sql)
160
+    {
161
+        return genTableMapper.createTable(sql) == 0;
162
+    }
163
+
164
+    /**
165
+     * 导入表结构
166
+     * 
167
+     * @param tableList 导入表列表
168
+     */
169
+    @Override
170
+    @Transactional
171
+    public void importGenTable(List<GenTable> tableList, String operName)
172
+    {
173
+        try
174
+        {
175
+            for (GenTable table : tableList)
176
+            {
177
+                String tableName = table.getTableName();
178
+                GenUtils.initTable(table, operName);
179
+                int row = genTableMapper.insertGenTable(table);
180
+                if (row > 0)
181
+                {
182
+                    // 保存列信息
183
+                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
184
+                    for (GenTableColumn column : genTableColumns)
185
+                    {
186
+                        GenUtils.initColumnField(column, table);
187
+                        genTableColumnMapper.insertGenTableColumn(column);
188
+                    }
189
+                }
190
+            }
191
+        }
192
+        catch (Exception e)
193
+        {
194
+            throw new ServiceException("导入失败:" + e.getMessage());
195
+        }
196
+    }
197
+
198
+    /**
199
+     * 预览代码
200
+     * 
201
+     * @param tableId 表编号
202
+     * @return 预览数据列表
203
+     */
204
+    @Override
205
+    public Map<String, String> previewCode(Long tableId)
206
+    {
207
+        Map<String, String> dataMap = new LinkedHashMap<>();
208
+        // 查询表信息
209
+        GenTable table = genTableMapper.selectGenTableById(tableId);
210
+        // 设置主子表信息
211
+        setSubTable(table);
212
+        // 设置主键列信息
213
+        setPkColumn(table);
214
+        VelocityInitializer.initVelocity();
215
+
216
+        VelocityContext context = VelocityUtils.prepareContext(table);
217
+
218
+        // 获取模板列表
219
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
220
+        for (String template : templates)
221
+        {
222
+            // 渲染模板
223
+            StringWriter sw = new StringWriter();
224
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
225
+            tpl.merge(context, sw);
226
+            dataMap.put(template, sw.toString());
227
+        }
228
+        return dataMap;
229
+    }
230
+
231
+    /**
232
+     * 生成代码(下载方式)
233
+     * 
234
+     * @param tableName 表名称
235
+     * @return 数据
236
+     */
237
+    @Override
238
+    public byte[] downloadCode(String tableName)
239
+    {
240
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
241
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
242
+        generatorCode(tableName, zip);
243
+        IOUtils.closeQuietly(zip);
244
+        return outputStream.toByteArray();
245
+    }
246
+
247
+    /**
248
+     * 生成代码(自定义路径)
249
+     * 
250
+     * @param tableName 表名称
251
+     */
252
+    @Override
253
+    public void generatorCode(String tableName)
254
+    {
255
+        // 查询表信息
256
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
257
+        // 设置主子表信息
258
+        setSubTable(table);
259
+        // 设置主键列信息
260
+        setPkColumn(table);
261
+
262
+        VelocityInitializer.initVelocity();
263
+
264
+        VelocityContext context = VelocityUtils.prepareContext(table);
265
+
266
+        // 获取模板列表
267
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
268
+        for (String template : templates)
269
+        {
270
+            if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
271
+            {
272
+                // 渲染模板
273
+                StringWriter sw = new StringWriter();
274
+                Template tpl = Velocity.getTemplate(template, Constants.UTF8);
275
+                tpl.merge(context, sw);
276
+                try
277
+                {
278
+                    String path = getGenPath(table, template);
279
+                    FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
280
+                }
281
+                catch (IOException e)
282
+                {
283
+                    throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
284
+                }
285
+            }
286
+        }
287
+    }
288
+
289
+    /**
290
+     * 同步数据库
291
+     * 
292
+     * @param tableName 表名称
293
+     */
294
+    @Override
295
+    @Transactional
296
+    public void synchDb(String tableName)
297
+    {
298
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
299
+        List<GenTableColumn> tableColumns = table.getColumns();
300
+        Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));
301
+
302
+        List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
303
+        if (StringUtils.isEmpty(dbTableColumns))
304
+        {
305
+            throw new ServiceException("同步数据失败,原表结构不存在");
306
+        }
307
+        List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
308
+
309
+        dbTableColumns.forEach(column -> {
310
+            GenUtils.initColumnField(column, table);
311
+            if (tableColumnMap.containsKey(column.getColumnName()))
312
+            {
313
+                GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
314
+                column.setColumnId(prevColumn.getColumnId());
315
+                if (column.isList())
316
+                {
317
+                    // 如果是列表,继续保留查询方式/字典类型选项
318
+                    column.setDictType(prevColumn.getDictType());
319
+                    column.setQueryType(prevColumn.getQueryType());
320
+                }
321
+                if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
322
+                        && (column.isInsert() || column.isEdit())
323
+                        && ((column.isUsableColumn()) || (!column.isSuperColumn())))
324
+                {
325
+                    // 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项
326
+                    column.setIsRequired(prevColumn.getIsRequired());
327
+                    column.setHtmlType(prevColumn.getHtmlType());
328
+                }
329
+                genTableColumnMapper.updateGenTableColumn(column);
330
+            }
331
+            else
332
+            {
333
+                genTableColumnMapper.insertGenTableColumn(column);
334
+            }
335
+        });
336
+
337
+        List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
338
+        if (StringUtils.isNotEmpty(delColumns))
339
+        {
340
+            genTableColumnMapper.deleteGenTableColumns(delColumns);
341
+        }
342
+    }
343
+
344
+    /**
345
+     * 批量生成代码(下载方式)
346
+     * 
347
+     * @param tableNames 表数组
348
+     * @return 数据
349
+     */
350
+    @Override
351
+    public byte[] downloadCode(String[] tableNames)
352
+    {
353
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
354
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
355
+        for (String tableName : tableNames)
356
+        {
357
+            generatorCode(tableName, zip);
358
+        }
359
+        IOUtils.closeQuietly(zip);
360
+        return outputStream.toByteArray();
361
+    }
362
+
363
+    /**
364
+     * 查询表信息并生成代码
365
+     */
366
+    private void generatorCode(String tableName, ZipOutputStream zip)
367
+    {
368
+        // 查询表信息
369
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
370
+        // 设置主子表信息
371
+        setSubTable(table);
372
+        // 设置主键列信息
373
+        setPkColumn(table);
374
+
375
+        VelocityInitializer.initVelocity();
376
+
377
+        VelocityContext context = VelocityUtils.prepareContext(table);
378
+
379
+        // 获取模板列表
380
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
381
+        for (String template : templates)
382
+        {
383
+            // 渲染模板
384
+            StringWriter sw = new StringWriter();
385
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
386
+            tpl.merge(context, sw);
387
+            try
388
+            {
389
+                // 添加到zip
390
+                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
391
+                IOUtils.write(sw.toString(), zip, Constants.UTF8);
392
+                IOUtils.closeQuietly(sw);
393
+                zip.flush();
394
+                zip.closeEntry();
395
+            }
396
+            catch (IOException e)
397
+            {
398
+                log.error("渲染模板失败,表名:" + table.getTableName(), e);
399
+            }
400
+        }
401
+    }
402
+
403
+    /**
404
+     * 修改保存参数校验
405
+     * 
406
+     * @param genTable 业务信息
407
+     */
408
+    @Override
409
+    public void validateEdit(GenTable genTable)
410
+    {
411
+        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
412
+        {
413
+            String options = JSON.toJSONString(genTable.getParams());
414
+            JSONObject paramsObj = JSON.parseObject(options);
415
+            if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
416
+            {
417
+                throw new ServiceException("树编码字段不能为空");
418
+            }
419
+            else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
420
+            {
421
+                throw new ServiceException("树父编码字段不能为空");
422
+            }
423
+            else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
424
+            {
425
+                throw new ServiceException("树名称字段不能为空");
426
+            }
427
+        }
428
+        else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
429
+        {
430
+            if (StringUtils.isEmpty(genTable.getSubTableName()))
431
+            {
432
+                throw new ServiceException("关联子表的表名不能为空");
433
+            }
434
+            else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
435
+            {
436
+                throw new ServiceException("子表关联的外键名不能为空");
437
+            }
438
+        }
439
+    }
440
+
441
+    /**
442
+     * 设置主键列信息
443
+     * 
444
+     * @param table 业务表信息
445
+     */
446
+    public void setPkColumn(GenTable table)
447
+    {
448
+        for (GenTableColumn column : table.getColumns())
449
+        {
450
+            if (column.isPk())
451
+            {
452
+                table.setPkColumn(column);
453
+                break;
454
+            }
455
+        }
456
+        if (StringUtils.isNull(table.getPkColumn()))
457
+        {
458
+            table.setPkColumn(table.getColumns().get(0));
459
+        }
460
+        if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
461
+        {
462
+            for (GenTableColumn column : table.getSubTable().getColumns())
463
+            {
464
+                if (column.isPk())
465
+                {
466
+                    table.getSubTable().setPkColumn(column);
467
+                    break;
468
+                }
469
+            }
470
+            if (StringUtils.isNull(table.getSubTable().getPkColumn()))
471
+            {
472
+                table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
473
+            }
474
+        }
475
+    }
476
+
477
+    /**
478
+     * 设置主子表信息
479
+     * 
480
+     * @param table 业务表信息
481
+     */
482
+    public void setSubTable(GenTable table)
483
+    {
484
+        String subTableName = table.getSubTableName();
485
+        if (StringUtils.isNotEmpty(subTableName))
486
+        {
487
+            table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
488
+        }
489
+    }
490
+
491
+    /**
492
+     * 设置代码生成其他选项值
493
+     * 
494
+     * @param genTable 设置后的生成对象
495
+     */
496
+    public void setTableFromOptions(GenTable genTable)
497
+    {
498
+        JSONObject paramsObj = JSON.parseObject(genTable.getOptions());
499
+        if (StringUtils.isNotNull(paramsObj))
500
+        {
501
+            String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
502
+            String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
503
+            String treeName = paramsObj.getString(GenConstants.TREE_NAME);
504
+            Long parentMenuId = paramsObj.getLongValue(GenConstants.PARENT_MENU_ID);
505
+            String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
506
+
507
+            genTable.setTreeCode(treeCode);
508
+            genTable.setTreeParentCode(treeParentCode);
509
+            genTable.setTreeName(treeName);
510
+            genTable.setParentMenuId(parentMenuId);
511
+            genTable.setParentMenuName(parentMenuName);
512
+        }
513
+    }
514
+
515
+    /**
516
+     * 获取代码生成地址
517
+     * 
518
+     * @param table 业务表信息
519
+     * @param template 模板文件路径
520
+     * @return 生成地址
521
+     */
522
+    public static String getGenPath(GenTable table, String template)
523
+    {
524
+        String genPath = table.getGenPath();
525
+        if (StringUtils.equals(genPath, "/"))
526
+        {
527
+            return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
528
+        }
529
+        return genPath + File.separator + VelocityUtils.getFileName(template, table);
530
+    }
531
+}

+ 44 - 0
airport-generator/src/main/java/com/sundot/airport/generator/service/IGenTableColumnService.java

@@ -0,0 +1,44 @@
1
+package com.sundot.airport.generator.service;
2
+
3
+import java.util.List;
4
+import com.sundot.airport.generator.domain.GenTableColumn;
5
+
6
+/**
7
+ * 业务字段 服务层
8
+ * 
9
+ * @author ruoyi
10
+ */
11
+public interface IGenTableColumnService
12
+{
13
+    /**
14
+     * 查询业务字段列表
15
+     * 
16
+     * @param tableId 业务字段编号
17
+     * @return 业务字段集合
18
+     */
19
+    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
20
+
21
+    /**
22
+     * 新增业务字段
23
+     * 
24
+     * @param genTableColumn 业务字段信息
25
+     * @return 结果
26
+     */
27
+    public int insertGenTableColumn(GenTableColumn genTableColumn);
28
+
29
+    /**
30
+     * 修改业务字段
31
+     * 
32
+     * @param genTableColumn 业务字段信息
33
+     * @return 结果
34
+     */
35
+    public int updateGenTableColumn(GenTableColumn genTableColumn);
36
+
37
+    /**
38
+     * 删除业务字段信息
39
+     * 
40
+     * @param ids 需要删除的数据ID
41
+     * @return 结果
42
+     */
43
+    public int deleteGenTableColumnByIds(String ids);
44
+}

+ 130 - 0
airport-generator/src/main/java/com/sundot/airport/generator/service/IGenTableService.java

@@ -0,0 +1,130 @@
1
+package com.sundot.airport.generator.service;
2
+
3
+import java.util.List;
4
+import java.util.Map;
5
+import com.sundot.airport.generator.domain.GenTable;
6
+
7
+/**
8
+ * 业务 服务层
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+public interface IGenTableService
13
+{
14
+    /**
15
+     * 查询业务列表
16
+     * 
17
+     * @param genTable 业务信息
18
+     * @return 业务集合
19
+     */
20
+    public List<GenTable> selectGenTableList(GenTable genTable);
21
+
22
+    /**
23
+     * 查询据库列表
24
+     * 
25
+     * @param genTable 业务信息
26
+     * @return 数据库表集合
27
+     */
28
+    public List<GenTable> selectDbTableList(GenTable genTable);
29
+
30
+    /**
31
+     * 查询据库列表
32
+     * 
33
+     * @param tableNames 表名称组
34
+     * @return 数据库表集合
35
+     */
36
+    public List<GenTable> selectDbTableListByNames(String[] tableNames);
37
+
38
+    /**
39
+     * 查询所有表信息
40
+     * 
41
+     * @return 表信息集合
42
+     */
43
+    public List<GenTable> selectGenTableAll();
44
+
45
+    /**
46
+     * 查询业务信息
47
+     * 
48
+     * @param id 业务ID
49
+     * @return 业务信息
50
+     */
51
+    public GenTable selectGenTableById(Long id);
52
+
53
+    /**
54
+     * 修改业务
55
+     * 
56
+     * @param genTable 业务信息
57
+     * @return 结果
58
+     */
59
+    public void updateGenTable(GenTable genTable);
60
+
61
+    /**
62
+     * 删除业务信息
63
+     * 
64
+     * @param tableIds 需要删除的表数据ID
65
+     * @return 结果
66
+     */
67
+    public void deleteGenTableByIds(Long[] tableIds);
68
+
69
+    /**
70
+     * 创建表
71
+     *
72
+     * @param sql 创建表语句
73
+     * @return 结果
74
+     */
75
+    public boolean createTable(String sql);
76
+
77
+    /**
78
+     * 导入表结构
79
+     *
80
+     * @param tableList 导入表列表
81
+     * @param operName 操作人员
82
+     */
83
+    public void importGenTable(List<GenTable> tableList, String operName);
84
+
85
+    /**
86
+     * 预览代码
87
+     * 
88
+     * @param tableId 表编号
89
+     * @return 预览数据列表
90
+     */
91
+    public Map<String, String> previewCode(Long tableId);
92
+
93
+    /**
94
+     * 生成代码(下载方式)
95
+     * 
96
+     * @param tableName 表名称
97
+     * @return 数据
98
+     */
99
+    public byte[] downloadCode(String tableName);
100
+
101
+    /**
102
+     * 生成代码(自定义路径)
103
+     * 
104
+     * @param tableName 表名称
105
+     * @return 数据
106
+     */
107
+    public void generatorCode(String tableName);
108
+
109
+    /**
110
+     * 同步数据库
111
+     * 
112
+     * @param tableName 表名称
113
+     */
114
+    public void synchDb(String tableName);
115
+
116
+    /**
117
+     * 批量生成代码(下载方式)
118
+     * 
119
+     * @param tableNames 表数组
120
+     * @return 数据
121
+     */
122
+    public byte[] downloadCode(String[] tableNames);
123
+
124
+    /**
125
+     * 修改保存参数校验
126
+     * 
127
+     * @param genTable 业务信息
128
+     */
129
+    public void validateEdit(GenTable genTable);
130
+}

+ 257 - 0
airport-generator/src/main/java/com/sundot/airport/generator/util/GenUtils.java

@@ -0,0 +1,257 @@
1
+package com.sundot.airport.generator.util;
2
+
3
+import java.util.Arrays;
4
+import org.apache.commons.lang3.RegExUtils;
5
+import com.sundot.airport.common.constant.GenConstants;
6
+import com.sundot.airport.common.utils.StringUtils;
7
+import com.sundot.airport.generator.config.GenConfig;
8
+import com.sundot.airport.generator.domain.GenTable;
9
+import com.sundot.airport.generator.domain.GenTableColumn;
10
+
11
+/**
12
+ * 代码生成器 工具类
13
+ * 
14
+ * @author ruoyi
15
+ */
16
+public class GenUtils
17
+{
18
+    /**
19
+     * 初始化表信息
20
+     */
21
+    public static void initTable(GenTable genTable, String operName)
22
+    {
23
+        genTable.setClassName(convertClassName(genTable.getTableName()));
24
+        genTable.setPackageName(GenConfig.getPackageName());
25
+        genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
26
+        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
27
+        genTable.setFunctionName(replaceText(genTable.getTableComment()));
28
+        genTable.setFunctionAuthor(GenConfig.getAuthor());
29
+        genTable.setCreateBy(operName);
30
+    }
31
+
32
+    /**
33
+     * 初始化列属性字段
34
+     */
35
+    public static void initColumnField(GenTableColumn column, GenTable table)
36
+    {
37
+        String dataType = getDbType(column.getColumnType());
38
+        String columnName = column.getColumnName();
39
+        column.setTableId(table.getTableId());
40
+        column.setCreateBy(table.getCreateBy());
41
+        // 设置java字段名
42
+        column.setJavaField(StringUtils.toCamelCase(columnName));
43
+        // 设置默认类型
44
+        column.setJavaType(GenConstants.TYPE_STRING);
45
+        column.setQueryType(GenConstants.QUERY_EQ);
46
+
47
+        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
48
+        {
49
+            // 字符串长度超过500设置为文本域
50
+            Integer columnLength = getColumnLength(column.getColumnType());
51
+            String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
52
+            column.setHtmlType(htmlType);
53
+        }
54
+        else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
55
+        {
56
+            column.setJavaType(GenConstants.TYPE_DATE);
57
+            column.setHtmlType(GenConstants.HTML_DATETIME);
58
+        }
59
+        else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
60
+        {
61
+            column.setHtmlType(GenConstants.HTML_INPUT);
62
+
63
+            // 如果是浮点型 统一用BigDecimal
64
+            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
65
+            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
66
+            {
67
+                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
68
+            }
69
+            // 如果是整形
70
+            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
71
+            {
72
+                column.setJavaType(GenConstants.TYPE_INTEGER);
73
+            }
74
+            // 长整形
75
+            else
76
+            {
77
+                column.setJavaType(GenConstants.TYPE_LONG);
78
+            }
79
+        }
80
+
81
+        // 插入字段(默认所有字段都需要插入)
82
+        column.setIsInsert(GenConstants.REQUIRE);
83
+
84
+        // 编辑字段
85
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
86
+        {
87
+            column.setIsEdit(GenConstants.REQUIRE);
88
+        }
89
+        // 列表字段
90
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
91
+        {
92
+            column.setIsList(GenConstants.REQUIRE);
93
+        }
94
+        // 查询字段
95
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
96
+        {
97
+            column.setIsQuery(GenConstants.REQUIRE);
98
+        }
99
+
100
+        // 查询字段类型
101
+        if (StringUtils.endsWithIgnoreCase(columnName, "name"))
102
+        {
103
+            column.setQueryType(GenConstants.QUERY_LIKE);
104
+        }
105
+        // 状态字段设置单选框
106
+        if (StringUtils.endsWithIgnoreCase(columnName, "status"))
107
+        {
108
+            column.setHtmlType(GenConstants.HTML_RADIO);
109
+        }
110
+        // 类型&性别字段设置下拉框
111
+        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
112
+                || StringUtils.endsWithIgnoreCase(columnName, "sex"))
113
+        {
114
+            column.setHtmlType(GenConstants.HTML_SELECT);
115
+        }
116
+        // 图片字段设置图片上传控件
117
+        else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
118
+        {
119
+            column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
120
+        }
121
+        // 文件字段设置文件上传控件
122
+        else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
123
+        {
124
+            column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
125
+        }
126
+        // 内容字段设置富文本控件
127
+        else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
128
+        {
129
+            column.setHtmlType(GenConstants.HTML_EDITOR);
130
+        }
131
+    }
132
+
133
+    /**
134
+     * 校验数组是否包含指定值
135
+     * 
136
+     * @param arr 数组
137
+     * @param targetValue 值
138
+     * @return 是否包含
139
+     */
140
+    public static boolean arraysContains(String[] arr, String targetValue)
141
+    {
142
+        return Arrays.asList(arr).contains(targetValue);
143
+    }
144
+
145
+    /**
146
+     * 获取模块名
147
+     * 
148
+     * @param packageName 包名
149
+     * @return 模块名
150
+     */
151
+    public static String getModuleName(String packageName)
152
+    {
153
+        int lastIndex = packageName.lastIndexOf(".");
154
+        int nameLength = packageName.length();
155
+        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
156
+    }
157
+
158
+    /**
159
+     * 获取业务名
160
+     * 
161
+     * @param tableName 表名
162
+     * @return 业务名
163
+     */
164
+    public static String getBusinessName(String tableName)
165
+    {
166
+        int lastIndex = tableName.lastIndexOf("_");
167
+        int nameLength = tableName.length();
168
+        return StringUtils.substring(tableName, lastIndex + 1, nameLength);
169
+    }
170
+
171
+    /**
172
+     * 表名转换成Java类名
173
+     * 
174
+     * @param tableName 表名称
175
+     * @return 类名
176
+     */
177
+    public static String convertClassName(String tableName)
178
+    {
179
+        boolean autoRemovePre = GenConfig.getAutoRemovePre();
180
+        String tablePrefix = GenConfig.getTablePrefix();
181
+        if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix))
182
+        {
183
+            String[] searchList = StringUtils.split(tablePrefix, ",");
184
+            tableName = replaceFirst(tableName, searchList);
185
+        }
186
+        return StringUtils.convertToCamelCase(tableName);
187
+    }
188
+
189
+    /**
190
+     * 批量替换前缀
191
+     * 
192
+     * @param replacementm 替换值
193
+     * @param searchList 替换列表
194
+     * @return
195
+     */
196
+    public static String replaceFirst(String replacementm, String[] searchList)
197
+    {
198
+        String text = replacementm;
199
+        for (String searchString : searchList)
200
+        {
201
+            if (replacementm.startsWith(searchString))
202
+            {
203
+                text = replacementm.replaceFirst(searchString, "");
204
+                break;
205
+            }
206
+        }
207
+        return text;
208
+    }
209
+
210
+    /**
211
+     * 关键字替换
212
+     * 
213
+     * @param text 需要被替换的名字
214
+     * @return 替换后的名字
215
+     */
216
+    public static String replaceText(String text)
217
+    {
218
+        return RegExUtils.replaceAll(text, "(?:表|若依)", "");
219
+    }
220
+
221
+    /**
222
+     * 获取数据库类型字段
223
+     * 
224
+     * @param columnType 列类型
225
+     * @return 截取后的列类型
226
+     */
227
+    public static String getDbType(String columnType)
228
+    {
229
+        if (StringUtils.indexOf(columnType, "(") > 0)
230
+        {
231
+            return StringUtils.substringBefore(columnType, "(");
232
+        }
233
+        else
234
+        {
235
+            return columnType;
236
+        }
237
+    }
238
+
239
+    /**
240
+     * 获取字段长度
241
+     * 
242
+     * @param columnType 列类型
243
+     * @return 截取后的列类型
244
+     */
245
+    public static Integer getColumnLength(String columnType)
246
+    {
247
+        if (StringUtils.indexOf(columnType, "(") > 0)
248
+        {
249
+            String length = StringUtils.substringBetween(columnType, "(", ")");
250
+            return Integer.valueOf(length);
251
+        }
252
+        else
253
+        {
254
+            return 0;
255
+        }
256
+    }
257
+}

+ 34 - 0
airport-generator/src/main/java/com/sundot/airport/generator/util/VelocityInitializer.java

@@ -0,0 +1,34 @@
1
+package com.sundot.airport.generator.util;
2
+
3
+import java.util.Properties;
4
+import org.apache.velocity.app.Velocity;
5
+import com.sundot.airport.common.constant.Constants;
6
+
7
+/**
8
+ * VelocityEngine工厂
9
+ * 
10
+ * @author ruoyi
11
+ */
12
+public class VelocityInitializer
13
+{
14
+    /**
15
+     * 初始化vm方法
16
+     */
17
+    public static void initVelocity()
18
+    {
19
+        Properties p = new Properties();
20
+        try
21
+        {
22
+            // 加载classpath目录下的vm文件
23
+            p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
24
+            // 定义字符集
25
+            p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
26
+            // 初始化Velocity引擎,指定配置Properties
27
+            Velocity.init(p);
28
+        }
29
+        catch (Exception e)
30
+        {
31
+            throw new RuntimeException(e);
32
+        }
33
+    }
34
+}

+ 408 - 0
airport-generator/src/main/java/com/sundot/airport/generator/util/VelocityUtils.java

@@ -0,0 +1,408 @@
1
+package com.sundot.airport.generator.util;
2
+
3
+import java.util.ArrayList;
4
+import java.util.HashSet;
5
+import java.util.List;
6
+import java.util.Set;
7
+import org.apache.velocity.VelocityContext;
8
+import com.alibaba.fastjson2.JSON;
9
+import com.alibaba.fastjson2.JSONObject;
10
+import com.sundot.airport.common.constant.GenConstants;
11
+import com.sundot.airport.common.utils.DateUtils;
12
+import com.sundot.airport.common.utils.StringUtils;
13
+import com.sundot.airport.generator.domain.GenTable;
14
+import com.sundot.airport.generator.domain.GenTableColumn;
15
+
16
+/**
17
+ * 模板处理工具类
18
+ * 
19
+ * @author ruoyi
20
+ */
21
+public class VelocityUtils
22
+{
23
+    /** 项目空间路径 */
24
+    private static final String PROJECT_PATH = "main/java";
25
+
26
+    /** mybatis空间路径 */
27
+    private static final String MYBATIS_PATH = "main/resources/mapper";
28
+
29
+    /** 默认上级菜单,系统工具 */
30
+    private static final String DEFAULT_PARENT_MENU_ID = "3";
31
+
32
+    /**
33
+     * 设置模板变量信息
34
+     *
35
+     * @return 模板列表
36
+     */
37
+    public static VelocityContext prepareContext(GenTable genTable)
38
+    {
39
+        String moduleName = genTable.getModuleName();
40
+        String businessName = genTable.getBusinessName();
41
+        String packageName = genTable.getPackageName();
42
+        String tplCategory = genTable.getTplCategory();
43
+        String functionName = genTable.getFunctionName();
44
+
45
+        VelocityContext velocityContext = new VelocityContext();
46
+        velocityContext.put("tplCategory", genTable.getTplCategory());
47
+        velocityContext.put("tableName", genTable.getTableName());
48
+        velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
49
+        velocityContext.put("ClassName", genTable.getClassName());
50
+        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
51
+        velocityContext.put("moduleName", genTable.getModuleName());
52
+        velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
53
+        velocityContext.put("businessName", genTable.getBusinessName());
54
+        velocityContext.put("basePackage", getPackagePrefix(packageName));
55
+        velocityContext.put("packageName", packageName);
56
+        velocityContext.put("author", genTable.getFunctionAuthor());
57
+        velocityContext.put("datetime", DateUtils.getDate());
58
+        velocityContext.put("pkColumn", genTable.getPkColumn());
59
+        velocityContext.put("importList", getImportList(genTable));
60
+        velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
61
+        velocityContext.put("columns", genTable.getColumns());
62
+        velocityContext.put("table", genTable);
63
+        velocityContext.put("dicts", getDicts(genTable));
64
+        setMenuVelocityContext(velocityContext, genTable);
65
+        if (GenConstants.TPL_TREE.equals(tplCategory))
66
+        {
67
+            setTreeVelocityContext(velocityContext, genTable);
68
+        }
69
+        if (GenConstants.TPL_SUB.equals(tplCategory))
70
+        {
71
+            setSubVelocityContext(velocityContext, genTable);
72
+        }
73
+        return velocityContext;
74
+    }
75
+
76
+    public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
77
+    {
78
+        String options = genTable.getOptions();
79
+        JSONObject paramsObj = JSON.parseObject(options);
80
+        String parentMenuId = getParentMenuId(paramsObj);
81
+        context.put("parentMenuId", parentMenuId);
82
+    }
83
+
84
+    public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
85
+    {
86
+        String options = genTable.getOptions();
87
+        JSONObject paramsObj = JSON.parseObject(options);
88
+        String treeCode = getTreecode(paramsObj);
89
+        String treeParentCode = getTreeParentCode(paramsObj);
90
+        String treeName = getTreeName(paramsObj);
91
+
92
+        context.put("treeCode", treeCode);
93
+        context.put("treeParentCode", treeParentCode);
94
+        context.put("treeName", treeName);
95
+        context.put("expandColumn", getExpandColumn(genTable));
96
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
97
+        {
98
+            context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE));
99
+        }
100
+        if (paramsObj.containsKey(GenConstants.TREE_NAME))
101
+        {
102
+            context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME));
103
+        }
104
+    }
105
+
106
+    public static void setSubVelocityContext(VelocityContext context, GenTable genTable)
107
+    {
108
+        GenTable subTable = genTable.getSubTable();
109
+        String subTableName = genTable.getSubTableName();
110
+        String subTableFkName = genTable.getSubTableFkName();
111
+        String subClassName = genTable.getSubTable().getClassName();
112
+        String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName);
113
+
114
+        context.put("subTable", subTable);
115
+        context.put("subTableName", subTableName);
116
+        context.put("subTableFkName", subTableFkName);
117
+        context.put("subTableFkClassName", subTableFkClassName);
118
+        context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName));
119
+        context.put("subClassName", subClassName);
120
+        context.put("subclassName", StringUtils.uncapitalize(subClassName));
121
+        context.put("subImportList", getImportList(genTable.getSubTable()));
122
+    }
123
+
124
+    /**
125
+     * 获取模板信息
126
+     * @param tplCategory 生成的模板
127
+     * @param tplWebType 前端类型
128
+     * @return 模板列表
129
+     */
130
+    public static List<String> getTemplateList(String tplCategory, String tplWebType)
131
+    {
132
+        String useWebType = "vm/vue";
133
+        if ("element-plus".equals(tplWebType))
134
+        {
135
+            useWebType = "vm/vue/v3";
136
+        }
137
+        List<String> templates = new ArrayList<String>();
138
+        templates.add("vm/java/domain.java.vm");
139
+        templates.add("vm/java/mapper.java.vm");
140
+        templates.add("vm/java/service.java.vm");
141
+        templates.add("vm/java/serviceImpl.java.vm");
142
+        templates.add("vm/java/controller.java.vm");
143
+        templates.add("vm/xml/mapper.xml.vm");
144
+        templates.add("vm/sql/sql.vm");
145
+        templates.add("vm/js/api.js.vm");
146
+        if (GenConstants.TPL_CRUD.equals(tplCategory))
147
+        {
148
+            templates.add(useWebType + "/index.vue.vm");
149
+        }
150
+        else if (GenConstants.TPL_TREE.equals(tplCategory))
151
+        {
152
+            templates.add(useWebType + "/index-tree.vue.vm");
153
+        }
154
+        else if (GenConstants.TPL_SUB.equals(tplCategory))
155
+        {
156
+            templates.add(useWebType + "/index.vue.vm");
157
+            templates.add("vm/java/sub-domain.java.vm");
158
+        }
159
+        return templates;
160
+    }
161
+
162
+    /**
163
+     * 获取文件名
164
+     */
165
+    public static String getFileName(String template, GenTable genTable)
166
+    {
167
+        // 文件名称
168
+        String fileName = "";
169
+        // 包路径
170
+        String packageName = genTable.getPackageName();
171
+        // 模块名
172
+        String moduleName = genTable.getModuleName();
173
+        // 大写类名
174
+        String className = genTable.getClassName();
175
+        // 业务名称
176
+        String businessName = genTable.getBusinessName();
177
+
178
+        String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
179
+        String mybatisPath = MYBATIS_PATH + "/" + moduleName;
180
+        String vuePath = "vue";
181
+
182
+        if (template.contains("domain.java.vm"))
183
+        {
184
+            fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
185
+        }
186
+        if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory()))
187
+        {
188
+            fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
189
+        }
190
+        else if (template.contains("mapper.java.vm"))
191
+        {
192
+            fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
193
+        }
194
+        else if (template.contains("service.java.vm"))
195
+        {
196
+            fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
197
+        }
198
+        else if (template.contains("serviceImpl.java.vm"))
199
+        {
200
+            fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
201
+        }
202
+        else if (template.contains("controller.java.vm"))
203
+        {
204
+            fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
205
+        }
206
+        else if (template.contains("mapper.xml.vm"))
207
+        {
208
+            fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
209
+        }
210
+        else if (template.contains("sql.vm"))
211
+        {
212
+            fileName = businessName + "Menu.sql";
213
+        }
214
+        else if (template.contains("api.js.vm"))
215
+        {
216
+            fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
217
+        }
218
+        else if (template.contains("index.vue.vm"))
219
+        {
220
+            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
221
+        }
222
+        else if (template.contains("index-tree.vue.vm"))
223
+        {
224
+            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
225
+        }
226
+        return fileName;
227
+    }
228
+
229
+    /**
230
+     * 获取包前缀
231
+     *
232
+     * @param packageName 包名称
233
+     * @return 包前缀名称
234
+     */
235
+    public static String getPackagePrefix(String packageName)
236
+    {
237
+        int lastIndex = packageName.lastIndexOf(".");
238
+        return StringUtils.substring(packageName, 0, lastIndex);
239
+    }
240
+
241
+    /**
242
+     * 根据列类型获取导入包
243
+     * 
244
+     * @param genTable 业务表对象
245
+     * @return 返回需要导入的包列表
246
+     */
247
+    public static HashSet<String> getImportList(GenTable genTable)
248
+    {
249
+        List<GenTableColumn> columns = genTable.getColumns();
250
+        GenTable subGenTable = genTable.getSubTable();
251
+        HashSet<String> importList = new HashSet<String>();
252
+        if (StringUtils.isNotNull(subGenTable))
253
+        {
254
+            importList.add("java.util.List");
255
+        }
256
+        for (GenTableColumn column : columns)
257
+        {
258
+            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType()))
259
+            {
260
+                importList.add("java.util.Date");
261
+                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
262
+            }
263
+            else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType()))
264
+            {
265
+                importList.add("java.math.BigDecimal");
266
+            }
267
+        }
268
+        return importList;
269
+    }
270
+
271
+    /**
272
+     * 根据列类型获取字典组
273
+     * 
274
+     * @param genTable 业务表对象
275
+     * @return 返回字典组
276
+     */
277
+    public static String getDicts(GenTable genTable)
278
+    {
279
+        List<GenTableColumn> columns = genTable.getColumns();
280
+        Set<String> dicts = new HashSet<String>();
281
+        addDicts(dicts, columns);
282
+        if (StringUtils.isNotNull(genTable.getSubTable()))
283
+        {
284
+            List<GenTableColumn> subColumns = genTable.getSubTable().getColumns();
285
+            addDicts(dicts, subColumns);
286
+        }
287
+        return StringUtils.join(dicts, ", ");
288
+    }
289
+
290
+    /**
291
+     * 添加字典列表
292
+     * 
293
+     * @param dicts 字典列表
294
+     * @param columns 列集合
295
+     */
296
+    public static void addDicts(Set<String> dicts, List<GenTableColumn> columns)
297
+    {
298
+        for (GenTableColumn column : columns)
299
+        {
300
+            if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
301
+                    column.getHtmlType(),
302
+                    new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX }))
303
+            {
304
+                dicts.add("'" + column.getDictType() + "'");
305
+            }
306
+        }
307
+    }
308
+
309
+    /**
310
+     * 获取权限前缀
311
+     *
312
+     * @param moduleName 模块名称
313
+     * @param businessName 业务名称
314
+     * @return 返回权限前缀
315
+     */
316
+    public static String getPermissionPrefix(String moduleName, String businessName)
317
+    {
318
+        return StringUtils.format("{}:{}", moduleName, businessName);
319
+    }
320
+
321
+    /**
322
+     * 获取上级菜单ID字段
323
+     *
324
+     * @param paramsObj 生成其他选项
325
+     * @return 上级菜单ID字段
326
+     */
327
+    public static String getParentMenuId(JSONObject paramsObj)
328
+    {
329
+        if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
330
+                && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID)))
331
+        {
332
+            return paramsObj.getString(GenConstants.PARENT_MENU_ID);
333
+        }
334
+        return DEFAULT_PARENT_MENU_ID;
335
+    }
336
+
337
+    /**
338
+     * 获取树编码
339
+     *
340
+     * @param paramsObj 生成其他选项
341
+     * @return 树编码
342
+     */
343
+    public static String getTreecode(JSONObject paramsObj)
344
+    {
345
+        if (paramsObj.containsKey(GenConstants.TREE_CODE))
346
+        {
347
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
348
+        }
349
+        return StringUtils.EMPTY;
350
+    }
351
+
352
+    /**
353
+     * 获取树父编码
354
+     *
355
+     * @param paramsObj 生成其他选项
356
+     * @return 树父编码
357
+     */
358
+    public static String getTreeParentCode(JSONObject paramsObj)
359
+    {
360
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
361
+        {
362
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
363
+        }
364
+        return StringUtils.EMPTY;
365
+    }
366
+
367
+    /**
368
+     * 获取树名称
369
+     *
370
+     * @param paramsObj 生成其他选项
371
+     * @return 树名称
372
+     */
373
+    public static String getTreeName(JSONObject paramsObj)
374
+    {
375
+        if (paramsObj.containsKey(GenConstants.TREE_NAME))
376
+        {
377
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
378
+        }
379
+        return StringUtils.EMPTY;
380
+    }
381
+
382
+    /**
383
+     * 获取需要在哪一列上面显示展开按钮
384
+     *
385
+     * @param genTable 业务表对象
386
+     * @return 展开按钮列序号
387
+     */
388
+    public static int getExpandColumn(GenTable genTable)
389
+    {
390
+        String options = genTable.getOptions();
391
+        JSONObject paramsObj = JSON.parseObject(options);
392
+        String treeName = paramsObj.getString(GenConstants.TREE_NAME);
393
+        int num = 0;
394
+        for (GenTableColumn column : genTable.getColumns())
395
+        {
396
+            if (column.isList())
397
+            {
398
+                num++;
399
+                String columnName = column.getColumnName();
400
+                if (columnName.equals(treeName))
401
+                {
402
+                    break;
403
+                }
404
+            }
405
+        }
406
+        return num;
407
+    }
408
+}

+ 12 - 0
airport-generator/src/main/resources/generator.yml

@@ -0,0 +1,12 @@
1
+# 代码生成
2
+gen:
3
+  # 作者
4
+  author: ruoyi
5
+  # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
6
+  packageName: com.sundot.airport.system
7
+  # 自动去除表前缀,默认是false
8
+  autoRemovePre: false
9
+  # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
10
+  tablePrefix: sys_
11
+  # 是否允许生成文件覆盖到本地(自定义路径),默认不允许
12
+  allowOverwrite: false

+ 127 - 0
airport-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml

@@ -0,0 +1,127 @@
1
+<?xml version="1.0" encoding="UTF-8" ?>
2
+<!DOCTYPE mapper
3
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5
+<mapper namespace="com.sundot.airport.generator.mapper.GenTableColumnMapper">
6
+
7
+    <resultMap type="GenTableColumn" id="GenTableColumnResult">
8
+        <id     property="columnId"       column="column_id"      />
9
+        <result property="tableId"        column="table_id"       />
10
+        <result property="columnName"     column="column_name"    />
11
+        <result property="columnComment"  column="column_comment" />
12
+        <result property="columnType"     column="column_type"    />
13
+        <result property="javaType"       column="java_type"      />
14
+        <result property="javaField"      column="java_field"     />
15
+        <result property="isPk"           column="is_pk"          />
16
+        <result property="isIncrement"    column="is_increment"   />
17
+        <result property="isRequired"     column="is_required"    />
18
+        <result property="isInsert"       column="is_insert"      />
19
+        <result property="isEdit"         column="is_edit"        />
20
+        <result property="isList"         column="is_list"        />
21
+        <result property="isQuery"        column="is_query"       />
22
+        <result property="queryType"      column="query_type"     />
23
+        <result property="htmlType"       column="html_type"      />
24
+        <result property="dictType"       column="dict_type"      />
25
+        <result property="sort"           column="sort"           />
26
+        <result property="createBy"       column="create_by"      />
27
+        <result property="createTime"     column="create_time"    />
28
+        <result property="updateBy"       column="update_by"      />
29
+        <result property="updateTime"     column="update_time"    />
30
+    </resultMap>
31
+
32
+	<sql id="selectGenTableColumnVo">
33
+        select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column
34
+    </sql>
35
+
36
+    <select id="selectGenTableColumnListByTableId" parameterType="Long" resultMap="GenTableColumnResult">
37
+        <include refid="selectGenTableColumnVo"/>
38
+        where table_id = #{tableId}
39
+        order by sort
40
+    </select>
41
+
42
+    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
43
+		select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
44
+		from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
45
+		order by ordinal_position
46
+	</select>
47
+
48
+    <insert id="insertGenTableColumn" parameterType="GenTableColumn" useGeneratedKeys="true" keyProperty="columnId">
49
+        insert into gen_table_column (
50
+			<if test="tableId != null and tableId != ''">table_id,</if>
51
+			<if test="columnName != null and columnName != ''">column_name,</if>
52
+			<if test="columnComment != null and columnComment != ''">column_comment,</if>
53
+			<if test="columnType != null and columnType != ''">column_type,</if>
54
+			<if test="javaType != null and javaType != ''">java_type,</if>
55
+			<if test="javaField != null  and javaField != ''">java_field,</if>
56
+			<if test="isPk != null and isPk != ''">is_pk,</if>
57
+			<if test="isIncrement != null and isIncrement != ''">is_increment,</if>
58
+			<if test="isRequired != null and isRequired != ''">is_required,</if>
59
+			<if test="isInsert != null and isInsert != ''">is_insert,</if>
60
+			<if test="isEdit != null and isEdit != ''">is_edit,</if>
61
+			<if test="isList != null and isList != ''">is_list,</if>
62
+			<if test="isQuery != null and isQuery != ''">is_query,</if>
63
+			<if test="queryType != null and queryType != ''">query_type,</if>
64
+			<if test="htmlType != null and htmlType != ''">html_type,</if>
65
+			<if test="dictType != null and dictType != ''">dict_type,</if>
66
+			<if test="sort != null">sort,</if>
67
+			<if test="createBy != null and createBy != ''">create_by,</if>
68
+			create_time
69
+         )values(
70
+			<if test="tableId != null and tableId != ''">#{tableId},</if>
71
+			<if test="columnName != null and columnName != ''">#{columnName},</if>
72
+			<if test="columnComment != null and columnComment != ''">#{columnComment},</if>
73
+			<if test="columnType != null and columnType != ''">#{columnType},</if>
74
+			<if test="javaType != null and javaType != ''">#{javaType},</if>
75
+			<if test="javaField != null and javaField != ''">#{javaField},</if>
76
+			<if test="isPk != null and isPk != ''">#{isPk},</if>
77
+			<if test="isIncrement != null and isIncrement != ''">#{isIncrement},</if>
78
+			<if test="isRequired != null and isRequired != ''">#{isRequired},</if>
79
+			<if test="isInsert != null and isInsert != ''">#{isInsert},</if>
80
+			<if test="isEdit != null and isEdit != ''">#{isEdit},</if>
81
+			<if test="isList != null and isList != ''">#{isList},</if>
82
+			<if test="isQuery != null and isQuery != ''">#{isQuery},</if>
83
+			<if test="queryType != null and queryType != ''">#{queryType},</if>
84
+			<if test="htmlType != null and htmlType != ''">#{htmlType},</if>
85
+			<if test="dictType != null and dictType != ''">#{dictType},</if>
86
+			<if test="sort != null">#{sort},</if>
87
+			<if test="createBy != null and createBy != ''">#{createBy},</if>
88
+			sysdate()
89
+         )
90
+    </insert>
91
+
92
+    <update id="updateGenTableColumn" parameterType="GenTableColumn">
93
+        update gen_table_column
94
+        <set>
95
+            <if test="columnComment != null">column_comment = #{columnComment},</if>
96
+            <if test="javaType != null">java_type = #{javaType},</if>
97
+            <if test="javaField != null">java_field = #{javaField},</if>
98
+            <if test="isInsert != null">is_insert = #{isInsert},</if>
99
+            <if test="isEdit != null">is_edit = #{isEdit},</if>
100
+            <if test="isList != null">is_list = #{isList},</if>
101
+            <if test="isQuery != null">is_query = #{isQuery},</if>
102
+            <if test="isRequired != null">is_required = #{isRequired},</if>
103
+            <if test="queryType != null">query_type = #{queryType},</if>
104
+            <if test="htmlType != null">html_type = #{htmlType},</if>
105
+            <if test="dictType != null">dict_type = #{dictType},</if>
106
+            <if test="sort != null">sort = #{sort},</if>
107
+            <if test="updateBy != null">update_by = #{updateBy},</if>
108
+            update_time = sysdate()
109
+        </set>
110
+        where column_id = #{columnId}
111
+    </update>
112
+
113
+    <delete id="deleteGenTableColumnByIds" parameterType="Long">
114
+        delete from gen_table_column where table_id in
115
+        <foreach collection="array" item="tableId" open="(" separator="," close=")">
116
+            #{tableId}
117
+        </foreach>
118
+    </delete>
119
+
120
+    <delete id="deleteGenTableColumns">
121
+        delete from gen_table_column where column_id in
122
+        <foreach collection="list" item="item" open="(" separator="," close=")">
123
+            #{item.columnId}
124
+        </foreach>
125
+    </delete>
126
+
127
+</mapper>

+ 210 - 0
airport-generator/src/main/resources/mapper/generator/GenTableMapper.xml

@@ -0,0 +1,210 @@
1
+<?xml version="1.0" encoding="UTF-8" ?>
2
+<!DOCTYPE mapper
3
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5
+<mapper namespace="com.sundot.airport.generator.mapper.GenTableMapper">
6
+
7
+	<resultMap type="GenTable" id="GenTableResult">
8
+	    <id     property="tableId"        column="table_id"          />
9
+		<result property="tableName"      column="table_name"        />
10
+		<result property="tableComment"   column="table_comment"     />
11
+		<result property="subTableName"   column="sub_table_name"    />
12
+		<result property="subTableFkName" column="sub_table_fk_name" />
13
+		<result property="className"      column="class_name"        />
14
+		<result property="tplCategory"    column="tpl_category"      />
15
+		<result property="tplWebType"     column="tpl_web_type"      />
16
+		<result property="packageName"    column="package_name"      />
17
+		<result property="moduleName"     column="module_name"       />
18
+		<result property="businessName"   column="business_name"     />
19
+		<result property="functionName"   column="function_name"     />
20
+		<result property="functionAuthor" column="function_author"   />
21
+		<result property="genType"        column="gen_type"          />
22
+		<result property="genPath"        column="gen_path"          />
23
+		<result property="options"        column="options"           />
24
+		<result property="createBy"       column="create_by"         />
25
+		<result property="createTime"     column="create_time"       />
26
+		<result property="updateBy"       column="update_by"         />
27
+		<result property="updateTime"     column="update_time"       />
28
+		<result property="remark"         column="remark"            />
29
+		<collection  property="columns"   javaType="java.util.List"  resultMap="GenTableColumnResult" />
30
+	</resultMap>
31
+	
32
+	<resultMap type="GenTableColumn" id="GenTableColumnResult">
33
+        <id     property="columnId"       column="column_id"      />
34
+        <result property="tableId"        column="table_id"       />
35
+        <result property="columnName"     column="column_name"    />
36
+        <result property="columnComment"  column="column_comment" />
37
+        <result property="columnType"     column="column_type"    />
38
+        <result property="javaType"       column="java_type"      />
39
+        <result property="javaField"      column="java_field"     />
40
+        <result property="isPk"           column="is_pk"          />
41
+        <result property="isIncrement"    column="is_increment"   />
42
+        <result property="isRequired"     column="is_required"    />
43
+        <result property="isInsert"       column="is_insert"      />
44
+        <result property="isEdit"         column="is_edit"        />
45
+        <result property="isList"         column="is_list"        />
46
+        <result property="isQuery"        column="is_query"       />
47
+        <result property="queryType"      column="query_type"     />
48
+        <result property="htmlType"       column="html_type"      />
49
+        <result property="dictType"       column="dict_type"      />
50
+        <result property="sort"           column="sort"           />
51
+        <result property="createBy"       column="create_by"      />
52
+        <result property="createTime"     column="create_time"    />
53
+        <result property="updateBy"       column="update_by"      />
54
+        <result property="updateTime"     column="update_time"    />
55
+    </resultMap>
56
+	
57
+	<sql id="selectGenTableVo">
58
+        select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, tpl_web_type, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
59
+    </sql>
60
+    
61
+    <select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
62
+		<include refid="selectGenTableVo"/>
63
+		<where>
64
+			<if test="tableName != null and tableName != ''">
65
+				AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
66
+			</if>
67
+			<if test="tableComment != null and tableComment != ''">
68
+				AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
69
+			</if>
70
+			<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
71
+				AND date_format(create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
72
+			</if>
73
+			<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
74
+				AND date_format(create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
75
+			</if>
76
+		</where>
77
+	</select>
78
+
79
+	<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
80
+		select table_name, table_comment, create_time, update_time from information_schema.tables
81
+		where table_schema = (select database())
82
+		AND table_name NOT LIKE 'qrtz\_%' AND table_name NOT LIKE 'gen\_%'
83
+		AND table_name NOT IN (select table_name from gen_table)
84
+		<if test="tableName != null and tableName != ''">
85
+			AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
86
+		</if>
87
+		<if test="tableComment != null and tableComment != ''">
88
+			AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
89
+		</if>
90
+		<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
91
+			AND date_format(create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
92
+		</if>
93
+		<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
94
+			AND date_format(create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
95
+		</if>
96
+        order by create_time desc
97
+	</select>
98
+	
99
+	<select id="selectDbTableListByNames" resultMap="GenTableResult">
100
+		select table_name, table_comment, create_time, update_time from information_schema.tables
101
+		where table_name NOT LIKE 'qrtz\_%' and table_name NOT LIKE 'gen\_%' and table_schema = (select database())
102
+		and table_name in
103
+	    <foreach collection="array" item="name" open="(" separator="," close=")">
104
+ 			#{name}
105
+        </foreach> 
106
+	</select>
107
+	
108
+	<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
109
+		select table_name, table_comment, create_time, update_time from information_schema.tables
110
+		where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
111
+		and table_name = #{tableName}
112
+	</select>
113
+	
114
+	<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
115
+	    SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
116
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
117
+		FROM gen_table t
118
+			 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
119
+		where t.table_id = #{tableId} order by c.sort
120
+	</select>
121
+	
122
+	<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
123
+	    SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
124
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
125
+		FROM gen_table t
126
+			 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
127
+		where t.table_name = #{tableName} order by c.sort
128
+	</select>
129
+	
130
+	<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
131
+	    SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
132
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
133
+		FROM gen_table t
134
+			 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
135
+		order by c.sort
136
+	</select>
137
+	
138
+	<insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
139
+        insert into gen_table (
140
+			<if test="tableName != null">table_name,</if>
141
+			<if test="tableComment != null and tableComment != ''">table_comment,</if>
142
+			<if test="className != null and className != ''">class_name,</if>
143
+			<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
144
+			<if test="tplWebType != null and tplWebType != ''">tpl_web_type,</if>
145
+			<if test="packageName != null and packageName != ''">package_name,</if>
146
+			<if test="moduleName != null and moduleName != ''">module_name,</if>
147
+			<if test="businessName != null and businessName != ''">business_name,</if>
148
+			<if test="functionName != null and functionName != ''">function_name,</if>
149
+			<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
150
+			<if test="genType != null and genType != ''">gen_type,</if>
151
+			<if test="genPath != null and genPath != ''">gen_path,</if>
152
+			<if test="remark != null and remark != ''">remark,</if>
153
+ 			<if test="createBy != null and createBy != ''">create_by,</if>
154
+			create_time
155
+         )values(
156
+			<if test="tableName != null">#{tableName},</if>
157
+			<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
158
+			<if test="className != null and className != ''">#{className},</if>
159
+			<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
160
+			<if test="tplWebType != null and tplWebType != ''">#{tplWebType},</if>
161
+			<if test="packageName != null and packageName != ''">#{packageName},</if>
162
+			<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
163
+			<if test="businessName != null and businessName != ''">#{businessName},</if>
164
+			<if test="functionName != null and functionName != ''">#{functionName},</if>
165
+			<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
166
+			<if test="genType != null and genType != ''">#{genType},</if>
167
+			<if test="genPath != null and genPath != ''">#{genPath},</if>
168
+			<if test="remark != null and remark != ''">#{remark},</if>
169
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
170
+			sysdate()
171
+         )
172
+    </insert>
173
+    
174
+    <update id="createTable">
175
+        ${sql}
176
+    </update>
177
+    
178
+    <update id="updateGenTable" parameterType="GenTable">
179
+        update gen_table
180
+        <set>
181
+            <if test="tableName != null">table_name = #{tableName},</if>
182
+            <if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
183
+            <if test="subTableName != null">sub_table_name = #{subTableName},</if>
184
+            <if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
185
+            <if test="className != null and className != ''">class_name = #{className},</if>
186
+            <if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
187
+            <if test="genType != null and genType != ''">gen_type = #{genType},</if>
188
+            <if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
189
+            <if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
190
+            <if test="tplWebType != null and tplWebType != ''">tpl_web_type = #{tplWebType},</if>
191
+            <if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
192
+            <if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
193
+            <if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
194
+            <if test="functionName != null and functionName != ''">function_name = #{functionName},</if>
195
+            <if test="options != null and options != ''">options = #{options},</if>
196
+            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
197
+            <if test="remark != null">remark = #{remark},</if>
198
+            update_time = sysdate()
199
+        </set>
200
+        where table_id = #{tableId}
201
+    </update>
202
+    
203
+    <delete id="deleteGenTableByIds" parameterType="Long">
204
+        delete from gen_table where table_id in 
205
+        <foreach collection="array" item="tableId" open="(" separator="," close=")">
206
+            #{tableId}
207
+        </foreach>
208
+    </delete>
209
+
210
+</mapper>

+ 115 - 0
airport-generator/src/main/resources/vm/java/controller.java.vm

@@ -0,0 +1,115 @@
1
+package ${packageName}.controller;
2
+
3
+import java.util.List;
4
+import javax.servlet.http.HttpServletResponse;
5
+import org.springframework.security.access.prepost.PreAuthorize;
6
+import org.springframework.beans.factory.annotation.Autowired;
7
+import org.springframework.web.bind.annotation.GetMapping;
8
+import org.springframework.web.bind.annotation.PostMapping;
9
+import org.springframework.web.bind.annotation.PutMapping;
10
+import org.springframework.web.bind.annotation.DeleteMapping;
11
+import org.springframework.web.bind.annotation.PathVariable;
12
+import org.springframework.web.bind.annotation.RequestBody;
13
+import org.springframework.web.bind.annotation.RequestMapping;
14
+import org.springframework.web.bind.annotation.RestController;
15
+import com.sundot.airport.common.annotation.Log;
16
+import com.sundot.airport.common.core.controller.BaseController;
17
+import com.sundot.airport.common.core.domain.AjaxResult;
18
+import com.sundot.airport.common.enums.BusinessType;
19
+import ${packageName}.domain.${ClassName};
20
+import ${packageName}.service.I${ClassName}Service;
21
+import com.sundot.airport.common.utils.poi.ExcelUtil;
22
+#if($table.crud || $table.sub)
23
+import com.sundot.airport.common.core.page.TableDataInfo;
24
+#elseif($table.tree)
25
+#end
26
+
27
+/**
28
+ * ${functionName}Controller
29
+ * 
30
+ * @author ${author}
31
+ * @date ${datetime}
32
+ */
33
+@RestController
34
+@RequestMapping("/${moduleName}/${businessName}")
35
+public class ${ClassName}Controller extends BaseController
36
+{
37
+    @Autowired
38
+    private I${ClassName}Service ${className}Service;
39
+
40
+    /**
41
+     * 查询${functionName}列表
42
+     */
43
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
44
+    @GetMapping("/list")
45
+#if($table.crud || $table.sub)
46
+    public TableDataInfo list(${ClassName} ${className})
47
+    {
48
+        startPage();
49
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
50
+        return getDataTable(list);
51
+    }
52
+#elseif($table.tree)
53
+    public AjaxResult list(${ClassName} ${className})
54
+    {
55
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
56
+        return success(list);
57
+    }
58
+#end
59
+
60
+    /**
61
+     * 导出${functionName}列表
62
+     */
63
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
64
+    @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
65
+    @PostMapping("/export")
66
+    public void export(HttpServletResponse response, ${ClassName} ${className})
67
+    {
68
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
69
+        ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
70
+        util.exportExcel(response, list, "${functionName}数据");
71
+    }
72
+
73
+    /**
74
+     * 获取${functionName}详细信息
75
+     */
76
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
77
+    @GetMapping(value = "/{${pkColumn.javaField}}")
78
+    public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
79
+    {
80
+        return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
81
+    }
82
+
83
+    /**
84
+     * 新增${functionName}
85
+     */
86
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
87
+    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
88
+    @PostMapping
89
+    public AjaxResult add(@RequestBody ${ClassName} ${className})
90
+    {
91
+        return toAjax(${className}Service.insert${ClassName}(${className}));
92
+    }
93
+
94
+    /**
95
+     * 修改${functionName}
96
+     */
97
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
98
+    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
99
+    @PutMapping
100
+    public AjaxResult edit(@RequestBody ${ClassName} ${className})
101
+    {
102
+        return toAjax(${className}Service.update${ClassName}(${className}));
103
+    }
104
+
105
+    /**
106
+     * 删除${functionName}
107
+     */
108
+    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
109
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
110
+	@DeleteMapping("/{${pkColumn.javaField}s}")
111
+    public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
112
+    {
113
+        return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s));
114
+    }
115
+}

+ 105 - 0
airport-generator/src/main/resources/vm/java/domain.java.vm

@@ -0,0 +1,105 @@
1
+package ${packageName}.domain;
2
+
3
+#foreach ($import in $importList)
4
+import ${import};
5
+#end
6
+import org.apache.commons.lang3.builder.ToStringBuilder;
7
+import org.apache.commons.lang3.builder.ToStringStyle;
8
+import com.sundot.airport.common.annotation.Excel;
9
+#if($table.crud || $table.sub)
10
+import com.sundot.airport.common.core.domain.BaseEntity;
11
+#elseif($table.tree)
12
+import com.sundot.airport.common.core.domain.TreeEntity;
13
+#end
14
+
15
+/**
16
+ * ${functionName}对象 ${tableName}
17
+ * 
18
+ * @author ${author}
19
+ * @date ${datetime}
20
+ */
21
+#if($table.crud || $table.sub)
22
+#set($Entity="BaseEntity")
23
+#elseif($table.tree)
24
+#set($Entity="TreeEntity")
25
+#end
26
+public class ${ClassName} extends ${Entity}
27
+{
28
+    private static final long serialVersionUID = 1L;
29
+
30
+#foreach ($column in $columns)
31
+#if(!$table.isSuperColumn($column.javaField))
32
+    /** $column.columnComment */
33
+#if($column.list)
34
+#set($parentheseIndex=$column.columnComment.indexOf("("))
35
+#if($parentheseIndex != -1)
36
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
37
+#else
38
+#set($comment=$column.columnComment)
39
+#end
40
+#if($parentheseIndex != -1)
41
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
42
+#elseif($column.javaType == 'Date')
43
+    @JsonFormat(pattern = "yyyy-MM-dd")
44
+    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
45
+#else
46
+    @Excel(name = "${comment}")
47
+#end
48
+#end
49
+    private $column.javaType $column.javaField;
50
+
51
+#end
52
+#end
53
+#if($table.sub)
54
+    /** $table.subTable.functionName信息 */
55
+    private List<${subClassName}> ${subclassName}List;
56
+
57
+#end
58
+#foreach ($column in $columns)
59
+#if(!$table.isSuperColumn($column.javaField))
60
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
61
+#set($AttrName=$column.javaField)
62
+#else
63
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
64
+#end
65
+    public void set${AttrName}($column.javaType $column.javaField) 
66
+    {
67
+        this.$column.javaField = $column.javaField;
68
+    }
69
+
70
+    public $column.javaType get${AttrName}() 
71
+    {
72
+        return $column.javaField;
73
+    }
74
+
75
+#end
76
+#end
77
+#if($table.sub)
78
+    public List<${subClassName}> get${subClassName}List()
79
+    {
80
+        return ${subclassName}List;
81
+    }
82
+
83
+    public void set${subClassName}List(List<${subClassName}> ${subclassName}List)
84
+    {
85
+        this.${subclassName}List = ${subclassName}List;
86
+    }
87
+
88
+#end
89
+    @Override
90
+    public String toString() {
91
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
92
+#foreach ($column in $columns)
93
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
94
+#set($AttrName=$column.javaField)
95
+#else
96
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
97
+#end
98
+            .append("${column.javaField}", get${AttrName}())
99
+#end
100
+#if($table.sub)
101
+            .append("${subclassName}List", get${subClassName}List())
102
+#end
103
+            .toString();
104
+    }
105
+}

+ 91 - 0
airport-generator/src/main/resources/vm/java/mapper.java.vm

@@ -0,0 +1,91 @@
1
+package ${packageName}.mapper;
2
+
3
+import java.util.List;
4
+import ${packageName}.domain.${ClassName};
5
+#if($table.sub)
6
+import ${packageName}.domain.${subClassName};
7
+#end
8
+
9
+/**
10
+ * ${functionName}Mapper接口
11
+ * 
12
+ * @author ${author}
13
+ * @date ${datetime}
14
+ */
15
+public interface ${ClassName}Mapper 
16
+{
17
+    /**
18
+     * 查询${functionName}
19
+     * 
20
+     * @param ${pkColumn.javaField} ${functionName}主键
21
+     * @return ${functionName}
22
+     */
23
+    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
24
+
25
+    /**
26
+     * 查询${functionName}列表
27
+     * 
28
+     * @param ${className} ${functionName}
29
+     * @return ${functionName}集合
30
+     */
31
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
32
+
33
+    /**
34
+     * 新增${functionName}
35
+     * 
36
+     * @param ${className} ${functionName}
37
+     * @return 结果
38
+     */
39
+    public int insert${ClassName}(${ClassName} ${className});
40
+
41
+    /**
42
+     * 修改${functionName}
43
+     * 
44
+     * @param ${className} ${functionName}
45
+     * @return 结果
46
+     */
47
+    public int update${ClassName}(${ClassName} ${className});
48
+
49
+    /**
50
+     * 删除${functionName}
51
+     * 
52
+     * @param ${pkColumn.javaField} ${functionName}主键
53
+     * @return 结果
54
+     */
55
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
56
+
57
+    /**
58
+     * 批量删除${functionName}
59
+     * 
60
+     * @param ${pkColumn.javaField}s 需要删除的数据主键集合
61
+     * @return 结果
62
+     */
63
+    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
64
+#if($table.sub)
65
+
66
+    /**
67
+     * 批量删除${subTable.functionName}
68
+     * 
69
+     * @param ${pkColumn.javaField}s 需要删除的数据主键集合
70
+     * @return 结果
71
+     */
72
+    public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
73
+    
74
+    /**
75
+     * 批量新增${subTable.functionName}
76
+     * 
77
+     * @param ${subclassName}List ${subTable.functionName}列表
78
+     * @return 结果
79
+     */
80
+    public int batch${subClassName}(List<${subClassName}> ${subclassName}List);
81
+    
82
+
83
+    /**
84
+     * 通过${functionName}主键删除${subTable.functionName}信息
85
+     * 
86
+     * @param ${pkColumn.javaField} ${functionName}ID
87
+     * @return 结果
88
+     */
89
+    public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
90
+#end
91
+}

+ 61 - 0
airport-generator/src/main/resources/vm/java/service.java.vm

@@ -0,0 +1,61 @@
1
+package ${packageName}.service;
2
+
3
+import java.util.List;
4
+import ${packageName}.domain.${ClassName};
5
+
6
+/**
7
+ * ${functionName}Service接口
8
+ * 
9
+ * @author ${author}
10
+ * @date ${datetime}
11
+ */
12
+public interface I${ClassName}Service 
13
+{
14
+    /**
15
+     * 查询${functionName}
16
+     * 
17
+     * @param ${pkColumn.javaField} ${functionName}主键
18
+     * @return ${functionName}
19
+     */
20
+    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
21
+
22
+    /**
23
+     * 查询${functionName}列表
24
+     * 
25
+     * @param ${className} ${functionName}
26
+     * @return ${functionName}集合
27
+     */
28
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
29
+
30
+    /**
31
+     * 新增${functionName}
32
+     * 
33
+     * @param ${className} ${functionName}
34
+     * @return 结果
35
+     */
36
+    public int insert${ClassName}(${ClassName} ${className});
37
+
38
+    /**
39
+     * 修改${functionName}
40
+     * 
41
+     * @param ${className} ${functionName}
42
+     * @return 结果
43
+     */
44
+    public int update${ClassName}(${ClassName} ${className});
45
+
46
+    /**
47
+     * 批量删除${functionName}
48
+     * 
49
+     * @param ${pkColumn.javaField}s 需要删除的${functionName}主键集合
50
+     * @return 结果
51
+     */
52
+    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
53
+
54
+    /**
55
+     * 删除${functionName}信息
56
+     * 
57
+     * @param ${pkColumn.javaField} ${functionName}主键
58
+     * @return 结果
59
+     */
60
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
61
+}

+ 169 - 0
airport-generator/src/main/resources/vm/java/serviceImpl.java.vm

@@ -0,0 +1,169 @@
1
+package ${packageName}.service.impl;
2
+
3
+import java.util.List;
4
+#foreach ($column in $columns)
5
+#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
6
+import com.sundot.airport.common.utils.DateUtils;
7
+#break
8
+#end
9
+#end
10
+import org.springframework.beans.factory.annotation.Autowired;
11
+import org.springframework.stereotype.Service;
12
+#if($table.sub)
13
+import java.util.ArrayList;
14
+import com.sundot.airport.common.utils.StringUtils;
15
+import org.springframework.transaction.annotation.Transactional;
16
+import ${packageName}.domain.${subClassName};
17
+#end
18
+import ${packageName}.mapper.${ClassName}Mapper;
19
+import ${packageName}.domain.${ClassName};
20
+import ${packageName}.service.I${ClassName}Service;
21
+
22
+/**
23
+ * ${functionName}Service业务层处理
24
+ * 
25
+ * @author ${author}
26
+ * @date ${datetime}
27
+ */
28
+@Service
29
+public class ${ClassName}ServiceImpl implements I${ClassName}Service 
30
+{
31
+    @Autowired
32
+    private ${ClassName}Mapper ${className}Mapper;
33
+
34
+    /**
35
+     * 查询${functionName}
36
+     * 
37
+     * @param ${pkColumn.javaField} ${functionName}主键
38
+     * @return ${functionName}
39
+     */
40
+    @Override
41
+    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
42
+    {
43
+        return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
44
+    }
45
+
46
+    /**
47
+     * 查询${functionName}列表
48
+     * 
49
+     * @param ${className} ${functionName}
50
+     * @return ${functionName}
51
+     */
52
+    @Override
53
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className})
54
+    {
55
+        return ${className}Mapper.select${ClassName}List(${className});
56
+    }
57
+
58
+    /**
59
+     * 新增${functionName}
60
+     * 
61
+     * @param ${className} ${functionName}
62
+     * @return 结果
63
+     */
64
+#if($table.sub)
65
+    @Transactional
66
+#end
67
+    @Override
68
+    public int insert${ClassName}(${ClassName} ${className})
69
+    {
70
+#foreach ($column in $columns)
71
+#if($column.javaField == 'createTime')
72
+        ${className}.setCreateTime(DateUtils.getNowDate());
73
+#end
74
+#end
75
+#if($table.sub)
76
+        int rows = ${className}Mapper.insert${ClassName}(${className});
77
+        insert${subClassName}(${className});
78
+        return rows;
79
+#else
80
+        return ${className}Mapper.insert${ClassName}(${className});
81
+#end
82
+    }
83
+
84
+    /**
85
+     * 修改${functionName}
86
+     * 
87
+     * @param ${className} ${functionName}
88
+     * @return 结果
89
+     */
90
+#if($table.sub)
91
+    @Transactional
92
+#end
93
+    @Override
94
+    public int update${ClassName}(${ClassName} ${className})
95
+    {
96
+#foreach ($column in $columns)
97
+#if($column.javaField == 'updateTime')
98
+        ${className}.setUpdateTime(DateUtils.getNowDate());
99
+#end
100
+#end
101
+#if($table.sub)
102
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}());
103
+        insert${subClassName}(${className});
104
+#end
105
+        return ${className}Mapper.update${ClassName}(${className});
106
+    }
107
+
108
+    /**
109
+     * 批量删除${functionName}
110
+     * 
111
+     * @param ${pkColumn.javaField}s 需要删除的${functionName}主键
112
+     * @return 结果
113
+     */
114
+#if($table.sub)
115
+    @Transactional
116
+#end
117
+    @Override
118
+    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s)
119
+    {
120
+#if($table.sub)
121
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
122
+#end
123
+        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s);
124
+    }
125
+
126
+    /**
127
+     * 删除${functionName}信息
128
+     * 
129
+     * @param ${pkColumn.javaField} ${functionName}主键
130
+     * @return 结果
131
+     */
132
+#if($table.sub)
133
+    @Transactional
134
+#end
135
+    @Override
136
+    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
137
+    {
138
+#if($table.sub)
139
+        ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
140
+#end
141
+        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
142
+    }
143
+#if($table.sub)
144
+
145
+    /**
146
+     * 新增${subTable.functionName}信息
147
+     * 
148
+     * @param ${className} ${functionName}对象
149
+     */
150
+    public void insert${subClassName}(${ClassName} ${className})
151
+    {
152
+        List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
153
+        ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
154
+        if (StringUtils.isNotNull(${subclassName}List))
155
+        {
156
+            List<${subClassName}> list = new ArrayList<${subClassName}>();
157
+            for (${subClassName} ${subclassName} : ${subclassName}List)
158
+            {
159
+                ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});
160
+                list.add(${subclassName});
161
+            }
162
+            if (list.size() > 0)
163
+            {
164
+                ${className}Mapper.batch${subClassName}(list);
165
+            }
166
+        }
167
+    }
168
+#end
169
+}

+ 76 - 0
airport-generator/src/main/resources/vm/java/sub-domain.java.vm

@@ -0,0 +1,76 @@
1
+package ${packageName}.domain;
2
+
3
+#foreach ($import in $subImportList)
4
+import ${import};
5
+#end
6
+import org.apache.commons.lang3.builder.ToStringBuilder;
7
+import org.apache.commons.lang3.builder.ToStringStyle;
8
+import com.sundot.airport.common.annotation.Excel;
9
+import com.sundot.airport.common.core.domain.BaseEntity;
10
+
11
+/**
12
+ * ${subTable.functionName}对象 ${subTableName}
13
+ * 
14
+ * @author ${author}
15
+ * @date ${datetime}
16
+ */
17
+public class ${subClassName} extends BaseEntity
18
+{
19
+    private static final long serialVersionUID = 1L;
20
+
21
+#foreach ($column in $subTable.columns)
22
+#if(!$table.isSuperColumn($column.javaField))
23
+    /** $column.columnComment */
24
+#if($column.list)
25
+#set($parentheseIndex=$column.columnComment.indexOf("("))
26
+#if($parentheseIndex != -1)
27
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
28
+#else
29
+#set($comment=$column.columnComment)
30
+#end
31
+#if($parentheseIndex != -1)
32
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
33
+#elseif($column.javaType == 'Date')
34
+    @JsonFormat(pattern = "yyyy-MM-dd")
35
+    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
36
+#else
37
+    @Excel(name = "${comment}")
38
+#end
39
+#end
40
+    private $column.javaType $column.javaField;
41
+
42
+#end
43
+#end
44
+#foreach ($column in $subTable.columns)
45
+#if(!$table.isSuperColumn($column.javaField))
46
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
47
+#set($AttrName=$column.javaField)
48
+#else
49
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
50
+#end
51
+    public void set${AttrName}($column.javaType $column.javaField) 
52
+    {
53
+        this.$column.javaField = $column.javaField;
54
+    }
55
+
56
+    public $column.javaType get${AttrName}() 
57
+    {
58
+        return $column.javaField;
59
+    }
60
+#end
61
+#end
62
+
63
+    @Override
64
+    public String toString() {
65
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
66
+#foreach ($column in $subTable.columns)
67
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
68
+#set($AttrName=$column.javaField)
69
+#else
70
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
71
+#end
72
+            .append("${column.javaField}", get${AttrName}())
73
+#end
74
+            .toString();
75
+    }
76
+}

+ 44 - 0
airport-generator/src/main/resources/vm/js/api.js.vm

@@ -0,0 +1,44 @@
1
+import request from '@/utils/request'
2
+
3
+// 查询${functionName}列表
4
+export function list${BusinessName}(query) {
5
+  return request({
6
+    url: '/${moduleName}/${businessName}/list',
7
+    method: 'get',
8
+    params: query
9
+  })
10
+}
11
+
12
+// 查询${functionName}详细
13
+export function get${BusinessName}(${pkColumn.javaField}) {
14
+  return request({
15
+    url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
16
+    method: 'get'
17
+  })
18
+}
19
+
20
+// 新增${functionName}
21
+export function add${BusinessName}(data) {
22
+  return request({
23
+    url: '/${moduleName}/${businessName}',
24
+    method: 'post',
25
+    data: data
26
+  })
27
+}
28
+
29
+// 修改${functionName}
30
+export function update${BusinessName}(data) {
31
+  return request({
32
+    url: '/${moduleName}/${businessName}',
33
+    method: 'put',
34
+    data: data
35
+  })
36
+}
37
+
38
+// 删除${functionName}
39
+export function del${BusinessName}(${pkColumn.javaField}) {
40
+  return request({
41
+    url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
42
+    method: 'delete'
43
+  })
44
+}

+ 22 - 0
airport-generator/src/main/resources/vm/sql/sql.vm

@@ -0,0 +1,22 @@
1
+-- 菜单 SQL
2
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
3
+values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单');
4
+
5
+-- 按钮父菜单ID
6
+SELECT @parentId := LAST_INSERT_ID();
7
+
8
+-- 按钮 SQL
9
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
10
+values('${functionName}查询', @parentId, '1',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query',        '#', 'admin', sysdate(), '', null, '');
11
+
12
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
13
+values('${functionName}新增', @parentId, '2',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add',          '#', 'admin', sysdate(), '', null, '');
14
+
15
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
16
+values('${functionName}修改', @parentId, '3',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit',         '#', 'admin', sysdate(), '', null, '');
17
+
18
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
19
+values('${functionName}删除', @parentId, '4',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove',       '#', 'admin', sysdate(), '', null, '');
20
+
21
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
22
+values('${functionName}导出', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export',       '#', 'admin', sysdate(), '', null, '');

+ 505 - 0
airport-generator/src/main/resources/vm/vue/index-tree.vue.vm

@@ -0,0 +1,505 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
4
+#foreach($column in $columns)
5
+#if($column.query)
6
+#set($dictType=$column.dictType)
7
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
8
+#set($parentheseIndex=$column.columnComment.indexOf("("))
9
+#if($parentheseIndex != -1)
10
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
11
+#else
12
+#set($comment=$column.columnComment)
13
+#end
14
+#if($column.htmlType == "input")
15
+      <el-form-item label="${comment}" prop="${column.javaField}">
16
+        <el-input
17
+          v-model="queryParams.${column.javaField}"
18
+          placeholder="请输入${comment}"
19
+          clearable
20
+          @keyup.enter.native="handleQuery"
21
+        />
22
+      </el-form-item>
23
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
24
+      <el-form-item label="${comment}" prop="${column.javaField}">
25
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
26
+          <el-option
27
+            v-for="dict in dict.type.${dictType}"
28
+            :key="dict.value"
29
+            :label="dict.label"
30
+            :value="dict.value"
31
+          />
32
+        </el-select>
33
+      </el-form-item>
34
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
35
+      <el-form-item label="${comment}" prop="${column.javaField}">
36
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
37
+          <el-option label="请选择字典生成" value="" />
38
+        </el-select>
39
+      </el-form-item>
40
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
41
+      <el-form-item label="${comment}" prop="${column.javaField}">
42
+        <el-date-picker clearable
43
+          v-model="queryParams.${column.javaField}"
44
+          type="date"
45
+          value-format="yyyy-MM-dd"
46
+          placeholder="选择${comment}">
47
+        </el-date-picker>
48
+      </el-form-item>
49
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
50
+      <el-form-item label="${comment}">
51
+        <el-date-picker
52
+          v-model="daterange${AttrName}"
53
+          style="width: 240px"
54
+          value-format="yyyy-MM-dd"
55
+          type="daterange"
56
+          range-separator="-"
57
+          start-placeholder="开始日期"
58
+          end-placeholder="结束日期"
59
+        ></el-date-picker>
60
+      </el-form-item>
61
+#end
62
+#end
63
+#end
64
+      <el-form-item>
65
+	    <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
66
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
67
+      </el-form-item>
68
+    </el-form>
69
+
70
+    <el-row :gutter="10" class="mb8">
71
+      <el-col :span="1.5">
72
+        <el-button
73
+          type="primary"
74
+          plain
75
+          icon="el-icon-plus"
76
+          size="mini"
77
+          @click="handleAdd"
78
+          v-hasPermi="['${permissionPrefix}:add']"
79
+        >新增</el-button>
80
+      </el-col>
81
+      <el-col :span="1.5">
82
+        <el-button
83
+          type="info"
84
+          plain
85
+          icon="el-icon-sort"
86
+          size="mini"
87
+          @click="toggleExpandAll"
88
+        >展开/折叠</el-button>
89
+      </el-col>
90
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
91
+    </el-row>
92
+
93
+    <el-table
94
+      v-if="refreshTable"
95
+      v-loading="loading"
96
+      :data="${businessName}List"
97
+      row-key="${treeCode}"
98
+      :default-expand-all="isExpandAll"
99
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
100
+    >
101
+#foreach($column in $columns)
102
+#set($javaField=$column.javaField)
103
+#set($parentheseIndex=$column.columnComment.indexOf("("))
104
+#if($parentheseIndex != -1)
105
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
106
+#else
107
+#set($comment=$column.columnComment)
108
+#end
109
+#if($column.pk)
110
+#elseif($column.list && $column.htmlType == "datetime")
111
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
112
+        <template slot-scope="scope">
113
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
114
+        </template>
115
+      </el-table-column>
116
+#elseif($column.list && $column.htmlType == "imageUpload")
117
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
118
+        <template slot-scope="scope">
119
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
120
+        </template>
121
+      </el-table-column>
122
+#elseif($column.list && "" != $column.dictType)
123
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
124
+        <template slot-scope="scope">
125
+#if($column.htmlType == "checkbox")
126
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
127
+#else
128
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
129
+#end
130
+        </template>
131
+      </el-table-column>
132
+#elseif($column.list && "" != $javaField)
133
+#if(${foreach.index} == 1)
134
+      <el-table-column label="${comment}" prop="${javaField}" />
135
+#else
136
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
137
+#end
138
+#end
139
+#end
140
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
141
+        <template slot-scope="scope">
142
+          <el-button
143
+            size="mini"
144
+            type="text"
145
+            icon="el-icon-edit"
146
+            @click="handleUpdate(scope.row)"
147
+            v-hasPermi="['${permissionPrefix}:edit']"
148
+          >修改</el-button>
149
+          <el-button
150
+            size="mini"
151
+            type="text"
152
+            icon="el-icon-plus"
153
+            @click="handleAdd(scope.row)"
154
+            v-hasPermi="['${permissionPrefix}:add']"
155
+          >新增</el-button>
156
+          <el-button
157
+            size="mini"
158
+            type="text"
159
+            icon="el-icon-delete"
160
+            @click="handleDelete(scope.row)"
161
+            v-hasPermi="['${permissionPrefix}:remove']"
162
+          >删除</el-button>
163
+        </template>
164
+      </el-table-column>
165
+    </el-table>
166
+
167
+    <!-- 添加或修改${functionName}对话框 -->
168
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
169
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
170
+#foreach($column in $columns)
171
+#set($field=$column.javaField)
172
+#if($column.insert && !$column.pk)
173
+#if(($column.usableColumn) || (!$column.superColumn))
174
+#set($parentheseIndex=$column.columnComment.indexOf("("))
175
+#if($parentheseIndex != -1)
176
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
177
+#else
178
+#set($comment=$column.columnComment)
179
+#end
180
+#set($dictType=$column.dictType)
181
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
182
+        <el-form-item label="${comment}" prop="${treeParentCode}">
183
+          <treeselect v-model="form.${treeParentCode}" :options="${businessName}Options" :normalizer="normalizer" placeholder="请选择${comment}" />
184
+        </el-form-item>
185
+#elseif($column.htmlType == "input")
186
+        <el-form-item label="${comment}" prop="${field}">
187
+          <el-input v-model="form.${field}" placeholder="请输入${comment}" />
188
+        </el-form-item>
189
+#elseif($column.htmlType == "imageUpload")
190
+        <el-form-item label="${comment}" prop="${field}">
191
+          <image-upload v-model="form.${field}"/>
192
+        </el-form-item>
193
+#elseif($column.htmlType == "fileUpload")
194
+        <el-form-item label="${comment}" prop="${field}">
195
+          <file-upload v-model="form.${field}"/>
196
+        </el-form-item>
197
+#elseif($column.htmlType == "editor")
198
+        <el-form-item label="${comment}">
199
+          <editor v-model="form.${field}" :min-height="192"/>
200
+        </el-form-item>
201
+#elseif($column.htmlType == "select" && "" != $dictType)
202
+        <el-form-item label="${comment}" prop="${field}">
203
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
204
+            <el-option
205
+              v-for="dict in dict.type.${dictType}"
206
+              :key="dict.value"
207
+              :label="dict.label"
208
+#if($column.javaType == "Integer" || $column.javaType == "Long")
209
+              :value="parseInt(dict.value)"
210
+#else
211
+              :value="dict.value"
212
+#end
213
+            ></el-option>
214
+          </el-select>
215
+        </el-form-item>
216
+#elseif($column.htmlType == "select" && $dictType)
217
+        <el-form-item label="${comment}" prop="${field}">
218
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
219
+            <el-option label="请选择字典生成" value="" />
220
+          </el-select>
221
+        </el-form-item>
222
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
223
+        <el-form-item label="${comment}" prop="${field}">
224
+          <el-checkbox-group v-model="form.${field}">
225
+            <el-checkbox
226
+              v-for="dict in dict.type.${dictType}"
227
+              :key="dict.value"
228
+              :label="dict.value">
229
+              {{dict.label}}
230
+            </el-checkbox>
231
+          </el-checkbox-group>
232
+        </el-form-item>
233
+#elseif($column.htmlType == "checkbox" && $dictType)
234
+        <el-form-item label="${comment}" prop="${field}">
235
+          <el-checkbox-group v-model="form.${field}">
236
+            <el-checkbox>请选择字典生成</el-checkbox>
237
+          </el-checkbox-group>
238
+        </el-form-item>
239
+#elseif($column.htmlType == "radio" && "" != $dictType)
240
+        <el-form-item label="${comment}" prop="${field}">
241
+          <el-radio-group v-model="form.${field}">
242
+            <el-radio
243
+              v-for="dict in dict.type.${dictType}"
244
+              :key="dict.value"
245
+#if($column.javaType == "Integer" || $column.javaType == "Long")
246
+              :label="parseInt(dict.value)"
247
+#else
248
+              :label="dict.value"
249
+#end
250
+            >{{dict.label}}</el-radio>
251
+          </el-radio-group>
252
+        </el-form-item>
253
+#elseif($column.htmlType == "radio" && $dictType)
254
+        <el-form-item label="${comment}" prop="${field}">
255
+          <el-radio-group v-model="form.${field}">
256
+            <el-radio label="1">请选择字典生成</el-radio>
257
+          </el-radio-group>
258
+        </el-form-item>
259
+#elseif($column.htmlType == "datetime")
260
+        <el-form-item label="${comment}" prop="${field}">
261
+          <el-date-picker clearable
262
+            v-model="form.${field}"
263
+            type="date"
264
+            value-format="yyyy-MM-dd"
265
+            placeholder="选择${comment}">
266
+          </el-date-picker>
267
+        </el-form-item>
268
+#elseif($column.htmlType == "textarea")
269
+        <el-form-item label="${comment}" prop="${field}">
270
+          <el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
271
+        </el-form-item>
272
+#end
273
+#end
274
+#end
275
+#end
276
+      </el-form>
277
+      <div slot="footer" class="dialog-footer">
278
+        <el-button type="primary" @click="submitForm">确 定</el-button>
279
+        <el-button @click="cancel">取 消</el-button>
280
+      </div>
281
+    </el-dialog>
282
+  </div>
283
+</template>
284
+
285
+<script>
286
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
287
+import Treeselect from "@riophae/vue-treeselect"
288
+import "@riophae/vue-treeselect/dist/vue-treeselect.css"
289
+
290
+export default {
291
+  name: "${BusinessName}",
292
+#if(${dicts} != '')
293
+  dicts: [${dicts}],
294
+#end
295
+  components: {
296
+    Treeselect
297
+  },
298
+  data() {
299
+    return {
300
+      // 遮罩层
301
+      loading: true,
302
+      // 显示搜索条件
303
+      showSearch: true,
304
+      // ${functionName}表格数据
305
+      ${businessName}List: [],
306
+      // ${functionName}树选项
307
+      ${businessName}Options: [],
308
+      // 弹出层标题
309
+      title: "",
310
+      // 是否显示弹出层
311
+      open: false,
312
+      // 是否展开,默认全部展开
313
+      isExpandAll: true,
314
+      // 重新渲染表格状态
315
+      refreshTable: true,
316
+#foreach ($column in $columns)
317
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
318
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
319
+      // $comment时间范围
320
+      daterange${AttrName}: [],
321
+#end
322
+#end
323
+      // 查询参数
324
+      queryParams: {
325
+#foreach ($column in $columns)
326
+#if($column.query)
327
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
328
+#end
329
+#end
330
+      },
331
+      // 表单参数
332
+      form: {},
333
+      // 表单校验
334
+      rules: {
335
+#foreach ($column in $columns)
336
+#if($column.required)
337
+#set($parentheseIndex=$column.columnComment.indexOf("("))
338
+#if($parentheseIndex != -1)
339
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
340
+#else
341
+#set($comment=$column.columnComment)
342
+#end
343
+        $column.javaField: [
344
+          { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
345
+        ]#if($foreach.count != $columns.size()),#end
346
+#end
347
+#end
348
+      }
349
+    }
350
+  },
351
+  created() {
352
+    this.getList()
353
+  },
354
+  methods: {
355
+    /** 查询${functionName}列表 */
356
+    getList() {
357
+      this.loading = true
358
+#foreach ($column in $columns)
359
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
360
+      this.queryParams.params = {}
361
+#break
362
+#end
363
+#end
364
+#foreach ($column in $columns)
365
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
366
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
367
+      if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
368
+        this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
369
+        this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
370
+      }
371
+#end
372
+#end
373
+      list${BusinessName}(this.queryParams).then(response => {
374
+        this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
375
+        this.loading = false
376
+      })
377
+    },
378
+    /** 转换${functionName}数据结构 */
379
+    normalizer(node) {
380
+      if (node.children && !node.children.length) {
381
+        delete node.children
382
+      }
383
+      return {
384
+        id: node.${treeCode},
385
+        label: node.${treeName},
386
+        children: node.children
387
+      }
388
+    },
389
+	/** 查询${functionName}下拉树结构 */
390
+    getTreeselect() {
391
+      list${BusinessName}().then(response => {
392
+        this.${businessName}Options = []
393
+        const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
394
+        data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
395
+        this.${businessName}Options.push(data)
396
+      })
397
+    },
398
+    // 取消按钮
399
+    cancel() {
400
+      this.open = false
401
+      this.reset()
402
+    },
403
+    // 表单重置
404
+    reset() {
405
+      this.form = {
406
+#foreach ($column in $columns)
407
+#if($column.htmlType == "checkbox")
408
+        $column.javaField: []#if($foreach.count != $columns.size()),#end
409
+#else
410
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
411
+#end
412
+#end
413
+      }
414
+      this.resetForm("form")
415
+    },
416
+    /** 搜索按钮操作 */
417
+    handleQuery() {
418
+      this.getList()
419
+    },
420
+    /** 重置按钮操作 */
421
+    resetQuery() {
422
+#foreach ($column in $columns)
423
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
424
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
425
+      this.daterange${AttrName} = []
426
+#end
427
+#end
428
+      this.resetForm("queryForm")
429
+      this.handleQuery()
430
+    },
431
+    /** 新增按钮操作 */
432
+    handleAdd(row) {
433
+      this.reset()
434
+      this.getTreeselect()
435
+      if (row != null && row.${treeCode}) {
436
+        this.form.${treeParentCode} = row.${treeCode}
437
+      } else {
438
+        this.form.${treeParentCode} = 0
439
+      }
440
+      this.open = true
441
+      this.title = "添加${functionName}"
442
+    },
443
+    /** 展开/折叠操作 */
444
+    toggleExpandAll() {
445
+      this.refreshTable = false
446
+      this.isExpandAll = !this.isExpandAll
447
+      this.$nextTick(() => {
448
+        this.refreshTable = true
449
+      })
450
+    },
451
+    /** 修改按钮操作 */
452
+    handleUpdate(row) {
453
+      this.reset()
454
+      this.getTreeselect()
455
+      if (row != null) {
456
+        this.form.${treeParentCode} = row.${treeParentCode}
457
+      }
458
+      get${BusinessName}(row.${pkColumn.javaField}).then(response => {
459
+        this.form = response.data
460
+#foreach ($column in $columns)
461
+#if($column.htmlType == "checkbox")
462
+        this.form.$column.javaField = this.form.${column.javaField}.split(",")
463
+#end
464
+#end
465
+        this.open = true
466
+        this.title = "修改${functionName}"
467
+      })
468
+    },
469
+    /** 提交按钮 */
470
+    submitForm() {
471
+      this.#[[$]]#refs["form"].validate(valid => {
472
+        if (valid) {
473
+#foreach ($column in $columns)
474
+#if($column.htmlType == "checkbox")
475
+          this.form.$column.javaField = this.form.${column.javaField}.join(",")
476
+#end
477
+#end
478
+          if (this.form.${pkColumn.javaField} != null) {
479
+            update${BusinessName}(this.form).then(response => {
480
+              this.#[[$modal]]#.msgSuccess("修改成功")
481
+              this.open = false
482
+              this.getList()
483
+            })
484
+          } else {
485
+            add${BusinessName}(this.form).then(response => {
486
+              this.#[[$modal]]#.msgSuccess("新增成功")
487
+              this.open = false
488
+              this.getList()
489
+            })
490
+          }
491
+        }
492
+      })
493
+    },
494
+    /** 删除按钮操作 */
495
+    handleDelete(row) {
496
+      this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
497
+        return del${BusinessName}(row.${pkColumn.javaField})
498
+      }).then(() => {
499
+        this.getList()
500
+        this.#[[$modal]]#.msgSuccess("删除成功")
501
+      }).catch(() => {})
502
+    }
503
+  }
504
+}
505
+</script>

+ 602 - 0
airport-generator/src/main/resources/vm/vue/index.vue.vm

@@ -0,0 +1,602 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
4
+#foreach($column in $columns)
5
+#if($column.query)
6
+#set($dictType=$column.dictType)
7
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
8
+#set($parentheseIndex=$column.columnComment.indexOf("("))
9
+#if($parentheseIndex != -1)
10
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
11
+#else
12
+#set($comment=$column.columnComment)
13
+#end
14
+#if($column.htmlType == "input")
15
+      <el-form-item label="${comment}" prop="${column.javaField}">
16
+        <el-input
17
+          v-model="queryParams.${column.javaField}"
18
+          placeholder="请输入${comment}"
19
+          clearable
20
+          @keyup.enter.native="handleQuery"
21
+        />
22
+      </el-form-item>
23
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
24
+      <el-form-item label="${comment}" prop="${column.javaField}">
25
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
26
+          <el-option
27
+            v-for="dict in dict.type.${dictType}"
28
+            :key="dict.value"
29
+            :label="dict.label"
30
+            :value="dict.value"
31
+          />
32
+        </el-select>
33
+      </el-form-item>
34
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
35
+      <el-form-item label="${comment}" prop="${column.javaField}">
36
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
37
+          <el-option label="请选择字典生成" value="" />
38
+        </el-select>
39
+      </el-form-item>
40
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
41
+      <el-form-item label="${comment}" prop="${column.javaField}">
42
+        <el-date-picker clearable
43
+          v-model="queryParams.${column.javaField}"
44
+          type="date"
45
+          value-format="yyyy-MM-dd"
46
+          placeholder="请选择${comment}">
47
+        </el-date-picker>
48
+      </el-form-item>
49
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
50
+      <el-form-item label="${comment}">
51
+        <el-date-picker
52
+          v-model="daterange${AttrName}"
53
+          style="width: 240px"
54
+          value-format="yyyy-MM-dd"
55
+          type="daterange"
56
+          range-separator="-"
57
+          start-placeholder="开始日期"
58
+          end-placeholder="结束日期"
59
+        ></el-date-picker>
60
+      </el-form-item>
61
+#end
62
+#end
63
+#end
64
+      <el-form-item>
65
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
66
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
67
+      </el-form-item>
68
+    </el-form>
69
+
70
+    <el-row :gutter="10" class="mb8">
71
+      <el-col :span="1.5">
72
+        <el-button
73
+          type="primary"
74
+          plain
75
+          icon="el-icon-plus"
76
+          size="mini"
77
+          @click="handleAdd"
78
+          v-hasPermi="['${permissionPrefix}:add']"
79
+        >新增</el-button>
80
+      </el-col>
81
+      <el-col :span="1.5">
82
+        <el-button
83
+          type="success"
84
+          plain
85
+          icon="el-icon-edit"
86
+          size="mini"
87
+          :disabled="single"
88
+          @click="handleUpdate"
89
+          v-hasPermi="['${permissionPrefix}:edit']"
90
+        >修改</el-button>
91
+      </el-col>
92
+      <el-col :span="1.5">
93
+        <el-button
94
+          type="danger"
95
+          plain
96
+          icon="el-icon-delete"
97
+          size="mini"
98
+          :disabled="multiple"
99
+          @click="handleDelete"
100
+          v-hasPermi="['${permissionPrefix}:remove']"
101
+        >删除</el-button>
102
+      </el-col>
103
+      <el-col :span="1.5">
104
+        <el-button
105
+          type="warning"
106
+          plain
107
+          icon="el-icon-download"
108
+          size="mini"
109
+          @click="handleExport"
110
+          v-hasPermi="['${permissionPrefix}:export']"
111
+        >导出</el-button>
112
+      </el-col>
113
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
114
+    </el-row>
115
+
116
+    <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
117
+      <el-table-column type="selection" width="55" align="center" />
118
+#foreach($column in $columns)
119
+#set($javaField=$column.javaField)
120
+#set($parentheseIndex=$column.columnComment.indexOf("("))
121
+#if($parentheseIndex != -1)
122
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
123
+#else
124
+#set($comment=$column.columnComment)
125
+#end
126
+#if($column.pk)
127
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
128
+#elseif($column.list && $column.htmlType == "datetime")
129
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
130
+        <template slot-scope="scope">
131
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
132
+        </template>
133
+      </el-table-column>
134
+#elseif($column.list && $column.htmlType == "imageUpload")
135
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
136
+        <template slot-scope="scope">
137
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
138
+        </template>
139
+      </el-table-column>
140
+#elseif($column.list && "" != $column.dictType)
141
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
142
+        <template slot-scope="scope">
143
+#if($column.htmlType == "checkbox")
144
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
145
+#else
146
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
147
+#end
148
+        </template>
149
+      </el-table-column>
150
+#elseif($column.list && "" != $javaField)
151
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
152
+#end
153
+#end
154
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
155
+        <template slot-scope="scope">
156
+          <el-button
157
+            size="mini"
158
+            type="text"
159
+            icon="el-icon-edit"
160
+            @click="handleUpdate(scope.row)"
161
+            v-hasPermi="['${permissionPrefix}:edit']"
162
+          >修改</el-button>
163
+          <el-button
164
+            size="mini"
165
+            type="text"
166
+            icon="el-icon-delete"
167
+            @click="handleDelete(scope.row)"
168
+            v-hasPermi="['${permissionPrefix}:remove']"
169
+          >删除</el-button>
170
+        </template>
171
+      </el-table-column>
172
+    </el-table>
173
+    
174
+    <pagination
175
+      v-show="total>0"
176
+      :total="total"
177
+      :page.sync="queryParams.pageNum"
178
+      :limit.sync="queryParams.pageSize"
179
+      @pagination="getList"
180
+    />
181
+
182
+    <!-- 添加或修改${functionName}对话框 -->
183
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
184
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
185
+#foreach($column in $columns)
186
+#set($field=$column.javaField)
187
+#if($column.insert && !$column.pk)
188
+#if(($column.usableColumn) || (!$column.superColumn))
189
+#set($parentheseIndex=$column.columnComment.indexOf("("))
190
+#if($parentheseIndex != -1)
191
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
192
+#else
193
+#set($comment=$column.columnComment)
194
+#end
195
+#set($dictType=$column.dictType)
196
+#if($column.htmlType == "input")
197
+        <el-form-item label="${comment}" prop="${field}">
198
+          <el-input v-model="form.${field}" placeholder="请输入${comment}" />
199
+        </el-form-item>
200
+#elseif($column.htmlType == "imageUpload")
201
+        <el-form-item label="${comment}" prop="${field}">
202
+          <image-upload v-model="form.${field}"/>
203
+        </el-form-item>
204
+#elseif($column.htmlType == "fileUpload")
205
+        <el-form-item label="${comment}" prop="${field}">
206
+          <file-upload v-model="form.${field}"/>
207
+        </el-form-item>
208
+#elseif($column.htmlType == "editor")
209
+        <el-form-item label="${comment}">
210
+          <editor v-model="form.${field}" :min-height="192"/>
211
+        </el-form-item>
212
+#elseif($column.htmlType == "select" && "" != $dictType)
213
+        <el-form-item label="${comment}" prop="${field}">
214
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
215
+            <el-option
216
+              v-for="dict in dict.type.${dictType}"
217
+              :key="dict.value"
218
+              :label="dict.label"
219
+#if($column.javaType == "Integer" || $column.javaType == "Long")
220
+              :value="parseInt(dict.value)"
221
+#else
222
+              :value="dict.value"
223
+#end
224
+            ></el-option>
225
+          </el-select>
226
+        </el-form-item>
227
+#elseif($column.htmlType == "select" && $dictType)
228
+        <el-form-item label="${comment}" prop="${field}">
229
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
230
+            <el-option label="请选择字典生成" value="" />
231
+          </el-select>
232
+        </el-form-item>
233
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
234
+        <el-form-item label="${comment}" prop="${field}">
235
+          <el-checkbox-group v-model="form.${field}">
236
+            <el-checkbox
237
+              v-for="dict in dict.type.${dictType}"
238
+              :key="dict.value"
239
+              :label="dict.value">
240
+              {{dict.label}}
241
+            </el-checkbox>
242
+          </el-checkbox-group>
243
+        </el-form-item>
244
+#elseif($column.htmlType == "checkbox" && $dictType)
245
+        <el-form-item label="${comment}" prop="${field}">
246
+          <el-checkbox-group v-model="form.${field}">
247
+            <el-checkbox>请选择字典生成</el-checkbox>
248
+          </el-checkbox-group>
249
+        </el-form-item>
250
+#elseif($column.htmlType == "radio" && "" != $dictType)
251
+        <el-form-item label="${comment}" prop="${field}">
252
+          <el-radio-group v-model="form.${field}">
253
+            <el-radio
254
+              v-for="dict in dict.type.${dictType}"
255
+              :key="dict.value"
256
+#if($column.javaType == "Integer" || $column.javaType == "Long")
257
+              :label="parseInt(dict.value)"
258
+#else
259
+              :label="dict.value"
260
+#end
261
+            >{{dict.label}}</el-radio>
262
+          </el-radio-group>
263
+        </el-form-item>
264
+#elseif($column.htmlType == "radio" && $dictType)
265
+        <el-form-item label="${comment}" prop="${field}">
266
+          <el-radio-group v-model="form.${field}">
267
+            <el-radio label="1">请选择字典生成</el-radio>
268
+          </el-radio-group>
269
+        </el-form-item>
270
+#elseif($column.htmlType == "datetime")
271
+        <el-form-item label="${comment}" prop="${field}">
272
+          <el-date-picker clearable
273
+            v-model="form.${field}"
274
+            type="date"
275
+            value-format="yyyy-MM-dd"
276
+            placeholder="请选择${comment}">
277
+          </el-date-picker>
278
+        </el-form-item>
279
+#elseif($column.htmlType == "textarea")
280
+        <el-form-item label="${comment}" prop="${field}">
281
+          <el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
282
+        </el-form-item>
283
+#end
284
+#end
285
+#end
286
+#end
287
+#if($table.sub)
288
+        <el-divider content-position="center">${subTable.functionName}信息</el-divider>
289
+        <el-row :gutter="10" class="mb8">
290
+          <el-col :span="1.5">
291
+            <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd${subClassName}">添加</el-button>
292
+          </el-col>
293
+          <el-col :span="1.5">
294
+            <el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDelete${subClassName}">删除</el-button>
295
+          </el-col>
296
+        </el-row>
297
+        <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
298
+          <el-table-column type="selection" width="50" align="center" />
299
+          <el-table-column label="序号" align="center" prop="index" width="50"/>
300
+#foreach($column in $subTable.columns)
301
+#set($javaField=$column.javaField)
302
+#set($parentheseIndex=$column.columnComment.indexOf("("))
303
+#if($parentheseIndex != -1)
304
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
305
+#else
306
+#set($comment=$column.columnComment)
307
+#end
308
+#if($column.pk || $javaField == ${subTableFkclassName})
309
+#elseif($column.list && $column.htmlType == "input")
310
+          <el-table-column label="$comment" prop="${javaField}" width="150">
311
+            <template slot-scope="scope">
312
+              <el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
313
+            </template>
314
+          </el-table-column>
315
+#elseif($column.list && $column.htmlType == "datetime")
316
+          <el-table-column label="$comment" prop="${javaField}" width="240">
317
+            <template slot-scope="scope">
318
+              <el-date-picker clearable v-model="scope.row.$javaField" type="date" value-format="yyyy-MM-dd" placeholder="请选择$comment" />
319
+            </template>
320
+          </el-table-column>
321
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
322
+          <el-table-column label="$comment" prop="${javaField}" width="150">
323
+            <template slot-scope="scope">
324
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
325
+                <el-option
326
+                  v-for="dict in dict.type.$column.dictType"
327
+                  :key="dict.value"
328
+                  :label="dict.label"
329
+                  :value="dict.value"
330
+                ></el-option>
331
+              </el-select>
332
+            </template>
333
+          </el-table-column>
334
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
335
+          <el-table-column label="$comment" prop="${javaField}" width="150">
336
+            <template slot-scope="scope">
337
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
338
+                <el-option label="请选择字典生成" value="" />
339
+              </el-select>
340
+            </template>
341
+          </el-table-column>
342
+#end
343
+#end
344
+        </el-table>
345
+#end
346
+      </el-form>
347
+      <div slot="footer" class="dialog-footer">
348
+        <el-button type="primary" @click="submitForm">确 定</el-button>
349
+        <el-button @click="cancel">取 消</el-button>
350
+      </div>
351
+    </el-dialog>
352
+  </div>
353
+</template>
354
+
355
+<script>
356
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
357
+
358
+export default {
359
+  name: "${BusinessName}",
360
+#if(${dicts} != '')
361
+  dicts: [${dicts}],
362
+#end
363
+  data() {
364
+    return {
365
+      // 遮罩层
366
+      loading: true,
367
+      // 选中数组
368
+      ids: [],
369
+#if($table.sub)
370
+      // 子表选中数据
371
+      checked${subClassName}: [],
372
+#end
373
+      // 非单个禁用
374
+      single: true,
375
+      // 非多个禁用
376
+      multiple: true,
377
+      // 显示搜索条件
378
+      showSearch: true,
379
+      // 总条数
380
+      total: 0,
381
+      // ${functionName}表格数据
382
+      ${businessName}List: [],
383
+#if($table.sub)
384
+      // ${subTable.functionName}表格数据
385
+      ${subclassName}List: [],
386
+#end
387
+      // 弹出层标题
388
+      title: "",
389
+      // 是否显示弹出层
390
+      open: false,
391
+#foreach ($column in $columns)
392
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
393
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
394
+      // $comment时间范围
395
+      daterange${AttrName}: [],
396
+#end
397
+#end
398
+      // 查询参数
399
+      queryParams: {
400
+        pageNum: 1,
401
+        pageSize: 10,
402
+#foreach ($column in $columns)
403
+#if($column.query)
404
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
405
+#end
406
+#end
407
+      },
408
+      // 表单参数
409
+      form: {},
410
+      // 表单校验
411
+      rules: {
412
+#foreach ($column in $columns)
413
+#if($column.required)
414
+#set($parentheseIndex=$column.columnComment.indexOf("("))
415
+#if($parentheseIndex != -1)
416
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
417
+#else
418
+#set($comment=$column.columnComment)
419
+#end
420
+        $column.javaField: [
421
+          { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
422
+        ]#if($foreach.count != $columns.size()),#end
423
+#end
424
+#end
425
+      }
426
+    }
427
+  },
428
+  created() {
429
+    this.getList()
430
+  },
431
+  methods: {
432
+    /** 查询${functionName}列表 */
433
+    getList() {
434
+      this.loading = true
435
+#foreach ($column in $columns)
436
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
437
+      this.queryParams.params = {}
438
+#break
439
+#end
440
+#end
441
+#foreach ($column in $columns)
442
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
443
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
444
+      if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
445
+        this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
446
+        this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
447
+      }
448
+#end
449
+#end
450
+      list${BusinessName}(this.queryParams).then(response => {
451
+        this.${businessName}List = response.rows
452
+        this.total = response.total
453
+        this.loading = false
454
+      })
455
+    },
456
+    // 取消按钮
457
+    cancel() {
458
+      this.open = false
459
+      this.reset()
460
+    },
461
+    // 表单重置
462
+    reset() {
463
+      this.form = {
464
+#foreach ($column in $columns)
465
+#if($column.htmlType == "checkbox")
466
+        $column.javaField: []#if($foreach.count != $columns.size()),#end
467
+#else
468
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
469
+#end
470
+#end
471
+      }
472
+#if($table.sub)
473
+      this.${subclassName}List = []
474
+#end
475
+      this.resetForm("form")
476
+    },
477
+    /** 搜索按钮操作 */
478
+    handleQuery() {
479
+      this.queryParams.pageNum = 1
480
+      this.getList()
481
+    },
482
+    /** 重置按钮操作 */
483
+    resetQuery() {
484
+#foreach ($column in $columns)
485
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
486
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
487
+      this.daterange${AttrName} = []
488
+#end
489
+#end
490
+      this.resetForm("queryForm")
491
+      this.handleQuery()
492
+    },
493
+    // 多选框选中数据
494
+    handleSelectionChange(selection) {
495
+      this.ids = selection.map(item => item.${pkColumn.javaField})
496
+      this.single = selection.length!==1
497
+      this.multiple = !selection.length
498
+    },
499
+    /** 新增按钮操作 */
500
+    handleAdd() {
501
+      this.reset()
502
+      this.open = true
503
+      this.title = "添加${functionName}"
504
+    },
505
+    /** 修改按钮操作 */
506
+    handleUpdate(row) {
507
+      this.reset()
508
+      const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
509
+      get${BusinessName}(${pkColumn.javaField}).then(response => {
510
+        this.form = response.data
511
+#foreach ($column in $columns)
512
+#if($column.htmlType == "checkbox")
513
+        this.form.$column.javaField = this.form.${column.javaField}.split(",")
514
+#end
515
+#end
516
+#if($table.sub)
517
+        this.${subclassName}List = response.data.${subclassName}List
518
+#end
519
+        this.open = true
520
+        this.title = "修改${functionName}"
521
+      })
522
+    },
523
+    /** 提交按钮 */
524
+    submitForm() {
525
+      this.#[[$]]#refs["form"].validate(valid => {
526
+        if (valid) {
527
+#foreach ($column in $columns)
528
+#if($column.htmlType == "checkbox")
529
+          this.form.$column.javaField = this.form.${column.javaField}.join(",")
530
+#end
531
+#end
532
+#if($table.sub)
533
+          this.form.${subclassName}List = this.${subclassName}List
534
+#end
535
+          if (this.form.${pkColumn.javaField} != null) {
536
+            update${BusinessName}(this.form).then(response => {
537
+              this.#[[$modal]]#.msgSuccess("修改成功")
538
+              this.open = false
539
+              this.getList()
540
+            })
541
+          } else {
542
+            add${BusinessName}(this.form).then(response => {
543
+              this.#[[$modal]]#.msgSuccess("新增成功")
544
+              this.open = false
545
+              this.getList()
546
+            })
547
+          }
548
+        }
549
+      })
550
+    },
551
+    /** 删除按钮操作 */
552
+    handleDelete(row) {
553
+      const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids
554
+      this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
555
+        return del${BusinessName}(${pkColumn.javaField}s)
556
+      }).then(() => {
557
+        this.getList()
558
+        this.#[[$modal]]#.msgSuccess("删除成功")
559
+      }).catch(() => {})
560
+    },
561
+#if($table.sub)
562
+	/** ${subTable.functionName}序号 */
563
+    row${subClassName}Index({ row, rowIndex }) {
564
+      row.index = rowIndex + 1
565
+    },
566
+    /** ${subTable.functionName}添加按钮操作 */
567
+    handleAdd${subClassName}() {
568
+      let obj = {}
569
+#foreach($column in $subTable.columns)
570
+#if($column.pk || $column.javaField == ${subTableFkclassName})
571
+#elseif($column.list && "" != $javaField)
572
+      obj.$column.javaField = ""
573
+#end
574
+#end
575
+      this.${subclassName}List.push(obj)
576
+    },
577
+    /** ${subTable.functionName}删除按钮操作 */
578
+    handleDelete${subClassName}() {
579
+      if (this.checked${subClassName}.length == 0) {
580
+        this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
581
+      } else {
582
+        const ${subclassName}List = this.${subclassName}List
583
+        const checked${subClassName} = this.checked${subClassName}
584
+        this.${subclassName}List = ${subclassName}List.filter(function(item) {
585
+          return checked${subClassName}.indexOf(item.index) == -1
586
+        })
587
+      }
588
+    },
589
+    /** 复选框选中数据 */
590
+    handle${subClassName}SelectionChange(selection) {
591
+      this.checked${subClassName} = selection.map(item => item.index)
592
+    },
593
+#end
594
+    /** 导出按钮操作 */
595
+    handleExport() {
596
+      this.download('${moduleName}/${businessName}/export', {
597
+        ...this.queryParams
598
+      }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
599
+    }
600
+  }
601
+}
602
+</script>

+ 474 - 0
airport-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm

@@ -0,0 +1,474 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
4
+#foreach($column in $columns)
5
+#if($column.query)
6
+#set($dictType=$column.dictType)
7
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
8
+#set($parentheseIndex=$column.columnComment.indexOf("("))
9
+#if($parentheseIndex != -1)
10
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
11
+#else
12
+#set($comment=$column.columnComment)
13
+#end
14
+#if($column.htmlType == "input")
15
+      <el-form-item label="${comment}" prop="${column.javaField}">
16
+        <el-input
17
+          v-model="queryParams.${column.javaField}"
18
+          placeholder="请输入${comment}"
19
+          clearable
20
+          @keyup.enter="handleQuery"
21
+        />
22
+      </el-form-item>
23
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
24
+      <el-form-item label="${comment}" prop="${column.javaField}">
25
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
26
+          <el-option
27
+            v-for="dict in ${dictType}"
28
+            :key="dict.value"
29
+            :label="dict.label"
30
+            :value="dict.value"
31
+          />
32
+        </el-select>
33
+      </el-form-item>
34
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
35
+      <el-form-item label="${comment}" prop="${column.javaField}">
36
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
37
+          <el-option label="请选择字典生成" value="" />
38
+        </el-select>
39
+      </el-form-item>
40
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
41
+      <el-form-item label="${comment}" prop="${column.javaField}">
42
+        <el-date-picker clearable
43
+          v-model="queryParams.${column.javaField}"
44
+          type="date"
45
+          value-format="YYYY-MM-DD"
46
+          placeholder="选择${comment}">
47
+        </el-date-picker>
48
+      </el-form-item>
49
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
50
+      <el-form-item label="${comment}" style="width: 308px">
51
+        <el-date-picker
52
+          v-model="daterange${AttrName}"
53
+          value-format="YYYY-MM-DD"
54
+          type="daterange"
55
+          range-separator="-"
56
+          start-placeholder="开始日期"
57
+          end-placeholder="结束日期"
58
+        ></el-date-picker>
59
+      </el-form-item>
60
+#end
61
+#end
62
+#end
63
+      <el-form-item>
64
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
65
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
66
+      </el-form-item>
67
+    </el-form>
68
+
69
+    <el-row :gutter="10" class="mb8">
70
+      <el-col :span="1.5">
71
+        <el-button
72
+          type="primary"
73
+          plain
74
+          icon="Plus"
75
+          @click="handleAdd"
76
+          v-hasPermi="['${permissionPrefix}:add']"
77
+        >新增</el-button>
78
+      </el-col>
79
+      <el-col :span="1.5">
80
+        <el-button
81
+          type="info"
82
+          plain
83
+          icon="Sort"
84
+          @click="toggleExpandAll"
85
+        >展开/折叠</el-button>
86
+      </el-col>
87
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
88
+    </el-row>
89
+
90
+    <el-table
91
+      v-if="refreshTable"
92
+      v-loading="loading"
93
+      :data="${businessName}List"
94
+      row-key="${treeCode}"
95
+      :default-expand-all="isExpandAll"
96
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
97
+    >
98
+#foreach($column in $columns)
99
+#set($javaField=$column.javaField)
100
+#set($parentheseIndex=$column.columnComment.indexOf("("))
101
+#if($parentheseIndex != -1)
102
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
103
+#else
104
+#set($comment=$column.columnComment)
105
+#end
106
+#if($column.pk)
107
+#elseif($column.list && $column.htmlType == "datetime")
108
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
109
+        <template #default="scope">
110
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
111
+        </template>
112
+      </el-table-column>
113
+#elseif($column.list && $column.htmlType == "imageUpload")
114
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
115
+        <template #default="scope">
116
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
117
+        </template>
118
+      </el-table-column>
119
+#elseif($column.list && "" != $column.dictType)
120
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
121
+        <template #default="scope">
122
+#if($column.htmlType == "checkbox")
123
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
124
+#else
125
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
126
+#end
127
+        </template>
128
+      </el-table-column>
129
+#elseif($column.list && "" != $javaField)
130
+#if(${foreach.index} == 1)
131
+      <el-table-column label="${comment}" prop="${javaField}" />
132
+#else
133
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
134
+#end
135
+#end
136
+#end
137
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
138
+        <template #default="scope">
139
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
140
+          <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${permissionPrefix}:add']">新增</el-button>
141
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
142
+        </template>
143
+      </el-table-column>
144
+    </el-table>
145
+
146
+    <!-- 添加或修改${functionName}对话框 -->
147
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
148
+      <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
149
+#foreach($column in $columns)
150
+#set($field=$column.javaField)
151
+#if($column.insert && !$column.pk)
152
+#if(($column.usableColumn) || (!$column.superColumn))
153
+#set($parentheseIndex=$column.columnComment.indexOf("("))
154
+#if($parentheseIndex != -1)
155
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
156
+#else
157
+#set($comment=$column.columnComment)
158
+#end
159
+#set($dictType=$column.dictType)
160
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
161
+        <el-form-item label="${comment}" prop="${treeParentCode}">
162
+          <el-tree-select
163
+            v-model="form.${treeParentCode}"
164
+            :data="${businessName}Options"
165
+            :props="{ value: '${treeCode}', label: '${treeName}', children: 'children' }"
166
+            value-key="${treeCode}"
167
+            placeholder="请选择${comment}"
168
+            check-strictly
169
+          />
170
+        </el-form-item>
171
+#elseif($column.htmlType == "input")
172
+        <el-form-item label="${comment}" prop="${field}">
173
+          <el-input v-model="form.${field}" placeholder="请输入${comment}" />
174
+        </el-form-item>
175
+#elseif($column.htmlType == "imageUpload")
176
+        <el-form-item label="${comment}" prop="${field}">
177
+          <image-upload v-model="form.${field}"/>
178
+        </el-form-item>
179
+#elseif($column.htmlType == "fileUpload")
180
+        <el-form-item label="${comment}" prop="${field}">
181
+          <file-upload v-model="form.${field}"/>
182
+        </el-form-item>
183
+#elseif($column.htmlType == "editor")
184
+        <el-form-item label="${comment}">
185
+          <editor v-model="form.${field}" :min-height="192"/>
186
+        </el-form-item>
187
+#elseif($column.htmlType == "select" && "" != $dictType)
188
+        <el-form-item label="${comment}" prop="${field}">
189
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
190
+            <el-option
191
+              v-for="dict in ${dictType}"
192
+              :key="dict.value"
193
+              :label="dict.label"
194
+#if($column.javaType == "Integer" || $column.javaType == "Long")
195
+              :value="parseInt(dict.value)"
196
+#else
197
+              :value="dict.value"
198
+#end
199
+            ></el-option>
200
+          </el-select>
201
+        </el-form-item>
202
+#elseif($column.htmlType == "select" && $dictType)
203
+        <el-form-item label="${comment}" prop="${field}">
204
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
205
+            <el-option label="请选择字典生成" value="" />
206
+          </el-select>
207
+        </el-form-item>
208
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
209
+        <el-form-item label="${comment}" prop="${field}">
210
+          <el-checkbox-group v-model="form.${field}">
211
+            <el-checkbox
212
+              v-for="dict in ${dictType}"
213
+              :key="dict.value"
214
+              :label="dict.value">
215
+              {{dict.label}}
216
+            </el-checkbox>
217
+          </el-checkbox-group>
218
+        </el-form-item>
219
+#elseif($column.htmlType == "checkbox" && $dictType)
220
+        <el-form-item label="${comment}" prop="${field}">
221
+          <el-checkbox-group v-model="form.${field}">
222
+            <el-checkbox>请选择字典生成</el-checkbox>
223
+          </el-checkbox-group>
224
+        </el-form-item>
225
+#elseif($column.htmlType == "radio" && "" != $dictType)
226
+        <el-form-item label="${comment}" prop="${field}">
227
+          <el-radio-group v-model="form.${field}">
228
+            <el-radio
229
+              v-for="dict in ${dictType}"
230
+              :key="dict.value"
231
+#if($column.javaType == "Integer" || $column.javaType == "Long")
232
+              :label="parseInt(dict.value)"
233
+#else
234
+              :label="dict.value"
235
+#end
236
+            >{{dict.label}}</el-radio>
237
+          </el-radio-group>
238
+        </el-form-item>
239
+#elseif($column.htmlType == "radio" && $dictType)
240
+        <el-form-item label="${comment}" prop="${field}">
241
+          <el-radio-group v-model="form.${field}">
242
+            <el-radio label="1">请选择字典生成</el-radio>
243
+          </el-radio-group>
244
+        </el-form-item>
245
+#elseif($column.htmlType == "datetime")
246
+        <el-form-item label="${comment}" prop="${field}">
247
+          <el-date-picker clearable
248
+            v-model="form.${field}"
249
+            type="date"
250
+            value-format="YYYY-MM-DD"
251
+            placeholder="选择${comment}">
252
+          </el-date-picker>
253
+        </el-form-item>
254
+#elseif($column.htmlType == "textarea")
255
+        <el-form-item label="${comment}" prop="${field}">
256
+          <el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
257
+        </el-form-item>
258
+#end
259
+#end
260
+#end
261
+#end
262
+      </el-form>
263
+      <template #footer>
264
+        <div class="dialog-footer">
265
+          <el-button type="primary" @click="submitForm">确 定</el-button>
266
+          <el-button @click="cancel">取 消</el-button>
267
+        </div>
268
+      </template>
269
+    </el-dialog>
270
+  </div>
271
+</template>
272
+
273
+<script setup name="${BusinessName}">
274
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
275
+
276
+const { proxy } = getCurrentInstance()
277
+#if(${dicts} != '')
278
+#set($dictsNoSymbol=$dicts.replace("'", ""))
279
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts})
280
+#end
281
+
282
+const ${businessName}List = ref([])
283
+const ${businessName}Options = ref([])
284
+const open = ref(false)
285
+const loading = ref(true)
286
+const showSearch = ref(true)
287
+const title = ref("")
288
+const isExpandAll = ref(true)
289
+const refreshTable = ref(true)
290
+#foreach ($column in $columns)
291
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
292
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
293
+const daterange${AttrName} = ref([])
294
+#end
295
+#end
296
+
297
+const data = reactive({
298
+  form: {},
299
+  queryParams: {
300
+    #foreach ($column in $columns)
301
+#if($column.query)
302
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
303
+#end
304
+#end
305
+  },
306
+  rules: {
307
+    #foreach ($column in $columns)
308
+#if($column.required)
309
+#set($parentheseIndex=$column.columnComment.indexOf("("))
310
+#if($parentheseIndex != -1)
311
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
312
+#else
313
+#set($comment=$column.columnComment)
314
+#end
315
+    $column.javaField: [
316
+      { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
317
+    ]#if($foreach.count != $columns.size()),#end
318
+#end
319
+#end
320
+  }
321
+})
322
+
323
+const { queryParams, form, rules } = toRefs(data)
324
+
325
+/** 查询${functionName}列表 */
326
+function getList() {
327
+  loading.value = true
328
+#foreach ($column in $columns)
329
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
330
+  queryParams.value.params = {}
331
+#break
332
+#end
333
+#end
334
+#foreach ($column in $columns)
335
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
336
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
337
+  if (null != daterange${AttrName} && '' != daterange${AttrName}) {
338
+    queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
339
+    queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
340
+  }
341
+#end
342
+#end
343
+  list${BusinessName}(queryParams.value).then(response => {
344
+    ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
345
+    loading.value = false
346
+  })
347
+}
348
+
349
+/** 查询${functionName}下拉树结构 */
350
+function getTreeselect() {
351
+  list${BusinessName}().then(response => {
352
+    ${businessName}Options.value = []
353
+    const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
354
+    data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
355
+    ${businessName}Options.value.push(data)
356
+  })
357
+}
358
+	
359
+// 取消按钮
360
+function cancel() {
361
+  open.value = false
362
+  reset()
363
+}
364
+
365
+// 表单重置
366
+function reset() {
367
+  form.value = {
368
+#foreach ($column in $columns)
369
+#if($column.htmlType == "checkbox")
370
+    $column.javaField: []#if($foreach.count != $columns.size()),#end
371
+#else
372
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
373
+#end
374
+#end
375
+  }
376
+  proxy.resetForm("${businessName}Ref")
377
+}
378
+
379
+/** 搜索按钮操作 */
380
+function handleQuery() {
381
+  getList()
382
+}
383
+
384
+/** 重置按钮操作 */
385
+function resetQuery() {
386
+#foreach ($column in $columns)
387
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
388
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
389
+  daterange${AttrName}.value = []
390
+#end
391
+#end
392
+  proxy.resetForm("queryRef")
393
+  handleQuery()
394
+}
395
+
396
+/** 新增按钮操作 */
397
+function handleAdd(row) {
398
+  reset()
399
+  getTreeselect()
400
+  if (row != null && row.${treeCode}) {
401
+    form.value.${treeParentCode} = row.${treeCode}
402
+  } else {
403
+    form.value.${treeParentCode} = 0
404
+  }
405
+  open.value = true
406
+  title.value = "添加${functionName}"
407
+}
408
+
409
+/** 展开/折叠操作 */
410
+function toggleExpandAll() {
411
+  refreshTable.value = false
412
+  isExpandAll.value = !isExpandAll.value
413
+  nextTick(() => {
414
+    refreshTable.value = true
415
+  })
416
+}
417
+
418
+/** 修改按钮操作 */
419
+async function handleUpdate(row) {
420
+  reset()
421
+  await getTreeselect()
422
+  if (row != null) {
423
+    form.value.${treeParentCode} = row.${treeParentCode}
424
+  }
425
+  get${BusinessName}(row.${pkColumn.javaField}).then(response => {
426
+    form.value = response.data
427
+#foreach ($column in $columns)
428
+#if($column.htmlType == "checkbox")
429
+    form.value.$column.javaField = form.value.${column.javaField}.split(",")
430
+#end
431
+#end
432
+    open.value = true
433
+    title.value = "修改${functionName}"
434
+  })
435
+}
436
+
437
+/** 提交按钮 */
438
+function submitForm() {
439
+  proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
440
+    if (valid) {
441
+#foreach ($column in $columns)
442
+#if($column.htmlType == "checkbox")
443
+      form.value.$column.javaField = form.value.${column.javaField}.join(",")
444
+#end
445
+#end
446
+      if (form.value.${pkColumn.javaField} != null) {
447
+        update${BusinessName}(form.value).then(response => {
448
+          proxy.#[[$modal]]#.msgSuccess("修改成功")
449
+          open.value = false
450
+          getList()
451
+        })
452
+      } else {
453
+        add${BusinessName}(form.value).then(response => {
454
+          proxy.#[[$modal]]#.msgSuccess("新增成功")
455
+          open.value = false
456
+          getList()
457
+        })
458
+      }
459
+    }
460
+  })
461
+}
462
+
463
+/** 删除按钮操作 */
464
+function handleDelete(row) {
465
+  proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
466
+    return del${BusinessName}(row.${pkColumn.javaField})
467
+  }).then(() => {
468
+    getList()
469
+    proxy.#[[$modal]]#.msgSuccess("删除成功")
470
+  }).catch(() => {})
471
+}
472
+
473
+getList()
474
+</script>

+ 590 - 0
airport-generator/src/main/resources/vm/vue/v3/index.vue.vm

@@ -0,0 +1,590 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
4
+#foreach($column in $columns)
5
+#if($column.query)
6
+#set($dictType=$column.dictType)
7
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
8
+#set($parentheseIndex=$column.columnComment.indexOf("("))
9
+#if($parentheseIndex != -1)
10
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
11
+#else
12
+#set($comment=$column.columnComment)
13
+#end
14
+#if($column.htmlType == "input")
15
+      <el-form-item label="${comment}" prop="${column.javaField}">
16
+        <el-input
17
+          v-model="queryParams.${column.javaField}"
18
+          placeholder="请输入${comment}"
19
+          clearable
20
+          @keyup.enter="handleQuery"
21
+        />
22
+      </el-form-item>
23
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
24
+      <el-form-item label="${comment}" prop="${column.javaField}">
25
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
26
+          <el-option
27
+            v-for="dict in ${dictType}"
28
+            :key="dict.value"
29
+            :label="dict.label"
30
+            :value="dict.value"
31
+          />
32
+        </el-select>
33
+      </el-form-item>
34
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
35
+      <el-form-item label="${comment}" prop="${column.javaField}">
36
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
37
+          <el-option label="请选择字典生成" value="" />
38
+        </el-select>
39
+      </el-form-item>
40
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
41
+      <el-form-item label="${comment}" prop="${column.javaField}">
42
+        <el-date-picker clearable
43
+          v-model="queryParams.${column.javaField}"
44
+          type="date"
45
+          value-format="YYYY-MM-DD"
46
+          placeholder="请选择${comment}">
47
+        </el-date-picker>
48
+      </el-form-item>
49
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
50
+      <el-form-item label="${comment}" style="width: 308px">
51
+        <el-date-picker
52
+          v-model="daterange${AttrName}"
53
+          value-format="YYYY-MM-DD"
54
+          type="daterange"
55
+          range-separator="-"
56
+          start-placeholder="开始日期"
57
+          end-placeholder="结束日期"
58
+        ></el-date-picker>
59
+      </el-form-item>
60
+#end
61
+#end
62
+#end
63
+      <el-form-item>
64
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
65
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
66
+      </el-form-item>
67
+    </el-form>
68
+
69
+    <el-row :gutter="10" class="mb8">
70
+      <el-col :span="1.5">
71
+        <el-button
72
+          type="primary"
73
+          plain
74
+          icon="Plus"
75
+          @click="handleAdd"
76
+          v-hasPermi="['${permissionPrefix}:add']"
77
+        >新增</el-button>
78
+      </el-col>
79
+      <el-col :span="1.5">
80
+        <el-button
81
+          type="success"
82
+          plain
83
+          icon="Edit"
84
+          :disabled="single"
85
+          @click="handleUpdate"
86
+          v-hasPermi="['${permissionPrefix}:edit']"
87
+        >修改</el-button>
88
+      </el-col>
89
+      <el-col :span="1.5">
90
+        <el-button
91
+          type="danger"
92
+          plain
93
+          icon="Delete"
94
+          :disabled="multiple"
95
+          @click="handleDelete"
96
+          v-hasPermi="['${permissionPrefix}:remove']"
97
+        >删除</el-button>
98
+      </el-col>
99
+      <el-col :span="1.5">
100
+        <el-button
101
+          type="warning"
102
+          plain
103
+          icon="Download"
104
+          @click="handleExport"
105
+          v-hasPermi="['${permissionPrefix}:export']"
106
+        >导出</el-button>
107
+      </el-col>
108
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
109
+    </el-row>
110
+
111
+    <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
112
+      <el-table-column type="selection" width="55" align="center" />
113
+#foreach($column in $columns)
114
+#set($javaField=$column.javaField)
115
+#set($parentheseIndex=$column.columnComment.indexOf("("))
116
+#if($parentheseIndex != -1)
117
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
118
+#else
119
+#set($comment=$column.columnComment)
120
+#end
121
+#if($column.pk)
122
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
123
+#elseif($column.list && $column.htmlType == "datetime")
124
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
125
+        <template #default="scope">
126
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
127
+        </template>
128
+      </el-table-column>
129
+#elseif($column.list && $column.htmlType == "imageUpload")
130
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
131
+        <template #default="scope">
132
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
133
+        </template>
134
+      </el-table-column>
135
+#elseif($column.list && "" != $column.dictType)
136
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
137
+        <template #default="scope">
138
+#if($column.htmlType == "checkbox")
139
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
140
+#else
141
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
142
+#end
143
+        </template>
144
+      </el-table-column>
145
+#elseif($column.list && "" != $javaField)
146
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
147
+#end
148
+#end
149
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
150
+        <template #default="scope">
151
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
152
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
153
+        </template>
154
+      </el-table-column>
155
+    </el-table>
156
+    
157
+    <pagination
158
+      v-show="total>0"
159
+      :total="total"
160
+      v-model:page="queryParams.pageNum"
161
+      v-model:limit="queryParams.pageSize"
162
+      @pagination="getList"
163
+    />
164
+
165
+    <!-- 添加或修改${functionName}对话框 -->
166
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
167
+      <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
168
+#foreach($column in $columns)
169
+#set($field=$column.javaField)
170
+#if($column.insert && !$column.pk)
171
+#if(($column.usableColumn) || (!$column.superColumn))
172
+#set($parentheseIndex=$column.columnComment.indexOf("("))
173
+#if($parentheseIndex != -1)
174
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
175
+#else
176
+#set($comment=$column.columnComment)
177
+#end
178
+#set($dictType=$column.dictType)
179
+#if($column.htmlType == "input")
180
+        <el-form-item label="${comment}" prop="${field}">
181
+          <el-input v-model="form.${field}" placeholder="请输入${comment}" />
182
+        </el-form-item>
183
+#elseif($column.htmlType == "imageUpload")
184
+        <el-form-item label="${comment}" prop="${field}">
185
+          <image-upload v-model="form.${field}"/>
186
+        </el-form-item>
187
+#elseif($column.htmlType == "fileUpload")
188
+        <el-form-item label="${comment}" prop="${field}">
189
+          <file-upload v-model="form.${field}"/>
190
+        </el-form-item>
191
+#elseif($column.htmlType == "editor")
192
+        <el-form-item label="${comment}">
193
+          <editor v-model="form.${field}" :min-height="192"/>
194
+        </el-form-item>
195
+#elseif($column.htmlType == "select" && "" != $dictType)
196
+        <el-form-item label="${comment}" prop="${field}">
197
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
198
+            <el-option
199
+              v-for="dict in ${dictType}"
200
+              :key="dict.value"
201
+              :label="dict.label"
202
+#if($column.javaType == "Integer" || $column.javaType == "Long")
203
+              :value="parseInt(dict.value)"
204
+#else
205
+              :value="dict.value"
206
+#end
207
+            ></el-option>
208
+          </el-select>
209
+        </el-form-item>
210
+#elseif($column.htmlType == "select" && $dictType)
211
+        <el-form-item label="${comment}" prop="${field}">
212
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
213
+            <el-option label="请选择字典生成" value="" />
214
+          </el-select>
215
+        </el-form-item>
216
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
217
+        <el-form-item label="${comment}" prop="${field}">
218
+          <el-checkbox-group v-model="form.${field}">
219
+            <el-checkbox
220
+              v-for="dict in ${dictType}"
221
+              :key="dict.value"
222
+              :label="dict.value">
223
+              {{dict.label}}
224
+            </el-checkbox>
225
+          </el-checkbox-group>
226
+        </el-form-item>
227
+#elseif($column.htmlType == "checkbox" && $dictType)
228
+        <el-form-item label="${comment}" prop="${field}">
229
+          <el-checkbox-group v-model="form.${field}">
230
+            <el-checkbox>请选择字典生成</el-checkbox>
231
+          </el-checkbox-group>
232
+        </el-form-item>
233
+#elseif($column.htmlType == "radio" && "" != $dictType)
234
+        <el-form-item label="${comment}" prop="${field}">
235
+          <el-radio-group v-model="form.${field}">
236
+            <el-radio
237
+              v-for="dict in ${dictType}"
238
+              :key="dict.value"
239
+#if($column.javaType == "Integer" || $column.javaType == "Long")
240
+              :label="parseInt(dict.value)"
241
+#else
242
+              :label="dict.value"
243
+#end
244
+            >{{dict.label}}</el-radio>
245
+          </el-radio-group>
246
+        </el-form-item>
247
+#elseif($column.htmlType == "radio" && $dictType)
248
+        <el-form-item label="${comment}" prop="${field}">
249
+          <el-radio-group v-model="form.${field}">
250
+            <el-radio label="1">请选择字典生成</el-radio>
251
+          </el-radio-group>
252
+        </el-form-item>
253
+#elseif($column.htmlType == "datetime")
254
+        <el-form-item label="${comment}" prop="${field}">
255
+          <el-date-picker clearable
256
+            v-model="form.${field}"
257
+            type="date"
258
+            value-format="YYYY-MM-DD"
259
+            placeholder="请选择${comment}">
260
+          </el-date-picker>
261
+        </el-form-item>
262
+#elseif($column.htmlType == "textarea")
263
+        <el-form-item label="${comment}" prop="${field}">
264
+          <el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
265
+        </el-form-item>
266
+#end
267
+#end
268
+#end
269
+#end
270
+#if($table.sub)
271
+        <el-divider content-position="center">${subTable.functionName}信息</el-divider>
272
+        <el-row :gutter="10" class="mb8">
273
+          <el-col :span="1.5">
274
+            <el-button type="primary" icon="Plus" @click="handleAdd${subClassName}">添加</el-button>
275
+          </el-col>
276
+          <el-col :span="1.5">
277
+            <el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">删除</el-button>
278
+          </el-col>
279
+        </el-row>
280
+        <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
281
+          <el-table-column type="selection" width="50" align="center" />
282
+          <el-table-column label="序号" align="center" prop="index" width="50"/>
283
+#foreach($column in $subTable.columns)
284
+#set($javaField=$column.javaField)
285
+#set($parentheseIndex=$column.columnComment.indexOf("("))
286
+#if($parentheseIndex != -1)
287
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
288
+#else
289
+#set($comment=$column.columnComment)
290
+#end
291
+#if($column.pk || $javaField == ${subTableFkclassName})
292
+#elseif($column.list && $column.htmlType == "input")
293
+          <el-table-column label="$comment" prop="${javaField}" width="150">
294
+            <template #default="scope">
295
+              <el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
296
+            </template>
297
+          </el-table-column>
298
+#elseif($column.list && $column.htmlType == "datetime")
299
+          <el-table-column label="$comment" prop="${javaField}" width="240">
300
+            <template #default="scope">
301
+              <el-date-picker clearable
302
+                v-model="scope.row.$javaField"
303
+                type="date"
304
+                value-format="YYYY-MM-DD"
305
+                placeholder="请选择$comment">
306
+              </el-date-picker>
307
+            </template>
308
+          </el-table-column>
309
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
310
+          <el-table-column label="$comment" prop="${javaField}" width="150">
311
+            <template #default="scope">
312
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
313
+                <el-option
314
+                  v-for="dict in $column.dictType"
315
+                  :key="dict.value"
316
+                  :label="dict.label"
317
+                  :value="dict.value"
318
+                ></el-option>
319
+              </el-select>
320
+            </template>
321
+          </el-table-column>
322
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
323
+          <el-table-column label="$comment" prop="${javaField}" width="150">
324
+            <template #default="scope">
325
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
326
+                <el-option label="请选择字典生成" value="" />
327
+              </el-select>
328
+            </template>
329
+          </el-table-column>
330
+#end
331
+#end
332
+        </el-table>
333
+#end
334
+      </el-form>
335
+      <template #footer>
336
+        <div class="dialog-footer">
337
+          <el-button type="primary" @click="submitForm">确 定</el-button>
338
+          <el-button @click="cancel">取 消</el-button>
339
+        </div>
340
+      </template>
341
+    </el-dialog>
342
+  </div>
343
+</template>
344
+
345
+<script setup name="${BusinessName}">
346
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
347
+
348
+const { proxy } = getCurrentInstance()
349
+#if(${dicts} != '')
350
+#set($dictsNoSymbol=$dicts.replace("'", ""))
351
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts})
352
+#end
353
+
354
+const ${businessName}List = ref([])
355
+#if($table.sub)
356
+const ${subclassName}List = ref([])
357
+#end
358
+const open = ref(false)
359
+const loading = ref(true)
360
+const showSearch = ref(true)
361
+const ids = ref([])
362
+#if($table.sub)
363
+const checked${subClassName} = ref([])
364
+#end
365
+const single = ref(true)
366
+const multiple = ref(true)
367
+const total = ref(0)
368
+const title = ref("")
369
+#foreach ($column in $columns)
370
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
371
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
372
+const daterange${AttrName} = ref([])
373
+#end
374
+#end
375
+
376
+const data = reactive({
377
+  form: {},
378
+  queryParams: {
379
+    pageNum: 1,
380
+    pageSize: 10,
381
+    #foreach ($column in $columns)
382
+#if($column.query)
383
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
384
+#end
385
+#end
386
+  },
387
+  rules: {
388
+    #foreach ($column in $columns)
389
+#if($column.required)
390
+#set($parentheseIndex=$column.columnComment.indexOf("("))
391
+#if($parentheseIndex != -1)
392
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
393
+#else
394
+#set($comment=$column.columnComment)
395
+#end
396
+    $column.javaField: [
397
+      { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
398
+    ]#if($foreach.count != $columns.size()),#end
399
+#end
400
+#end
401
+  }
402
+})
403
+
404
+const { queryParams, form, rules } = toRefs(data)
405
+
406
+/** 查询${functionName}列表 */
407
+function getList() {
408
+  loading.value = true
409
+#foreach ($column in $columns)
410
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
411
+  queryParams.value.params = {}
412
+#break
413
+#end
414
+#end
415
+#foreach ($column in $columns)
416
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
417
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
418
+  if (null != daterange${AttrName} && '' != daterange${AttrName}) {
419
+    queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
420
+    queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
421
+  }
422
+#end
423
+#end
424
+  list${BusinessName}(queryParams.value).then(response => {
425
+    ${businessName}List.value = response.rows
426
+    total.value = response.total
427
+    loading.value = false
428
+  })
429
+}
430
+
431
+// 取消按钮
432
+function cancel() {
433
+  open.value = false
434
+  reset()
435
+}
436
+
437
+// 表单重置
438
+function reset() {
439
+  form.value = {
440
+#foreach ($column in $columns)
441
+#if($column.htmlType == "checkbox")
442
+    $column.javaField: []#if($foreach.count != $columns.size()),#end
443
+#else
444
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
445
+#end
446
+#end
447
+  }
448
+#if($table.sub)
449
+  ${subclassName}List.value = []
450
+#end
451
+  proxy.resetForm("${businessName}Ref")
452
+}
453
+
454
+/** 搜索按钮操作 */
455
+function handleQuery() {
456
+  queryParams.value.pageNum = 1
457
+  getList()
458
+}
459
+
460
+/** 重置按钮操作 */
461
+function resetQuery() {
462
+#foreach ($column in $columns)
463
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
464
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
465
+  daterange${AttrName}.value = []
466
+#end
467
+#end
468
+  proxy.resetForm("queryRef")
469
+  handleQuery()
470
+}
471
+
472
+// 多选框选中数据
473
+function handleSelectionChange(selection) {
474
+  ids.value = selection.map(item => item.${pkColumn.javaField})
475
+  single.value = selection.length != 1
476
+  multiple.value = !selection.length
477
+}
478
+
479
+/** 新增按钮操作 */
480
+function handleAdd() {
481
+  reset()
482
+  open.value = true
483
+  title.value = "添加${functionName}"
484
+}
485
+
486
+/** 修改按钮操作 */
487
+function handleUpdate(row) {
488
+  reset()
489
+  const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
490
+  get${BusinessName}(_${pkColumn.javaField}).then(response => {
491
+    form.value = response.data
492
+#foreach ($column in $columns)
493
+#if($column.htmlType == "checkbox")
494
+    form.value.$column.javaField = form.value.${column.javaField}.split(",")
495
+#end
496
+#end
497
+#if($table.sub)
498
+    ${subclassName}List.value = response.data.${subclassName}List
499
+#end
500
+    open.value = true
501
+    title.value = "修改${functionName}"
502
+  })
503
+}
504
+
505
+/** 提交按钮 */
506
+function submitForm() {
507
+  proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
508
+    if (valid) {
509
+#foreach ($column in $columns)
510
+#if($column.htmlType == "checkbox")
511
+      form.value.$column.javaField = form.value.${column.javaField}.join(",")
512
+#end
513
+#end
514
+#if($table.sub)
515
+      form.value.${subclassName}List = ${subclassName}List.value
516
+#end
517
+      if (form.value.${pkColumn.javaField} != null) {
518
+        update${BusinessName}(form.value).then(response => {
519
+          proxy.#[[$modal]]#.msgSuccess("修改成功")
520
+          open.value = false
521
+          getList()
522
+        })
523
+      } else {
524
+        add${BusinessName}(form.value).then(response => {
525
+          proxy.#[[$modal]]#.msgSuccess("新增成功")
526
+          open.value = false
527
+          getList()
528
+        })
529
+      }
530
+    }
531
+  })
532
+}
533
+
534
+/** 删除按钮操作 */
535
+function handleDelete(row) {
536
+  const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value
537
+  proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
538
+    return del${BusinessName}(_${pkColumn.javaField}s)
539
+  }).then(() => {
540
+    getList()
541
+    proxy.#[[$modal]]#.msgSuccess("删除成功")
542
+  }).catch(() => {})
543
+}
544
+
545
+#if($table.sub)
546
+/** ${subTable.functionName}序号 */
547
+function row${subClassName}Index({ row, rowIndex }) {
548
+  row.index = rowIndex + 1
549
+}
550
+
551
+/** ${subTable.functionName}添加按钮操作 */
552
+function handleAdd${subClassName}() {
553
+  let obj = {}
554
+#foreach($column in $subTable.columns)
555
+#if($column.pk || $column.javaField == ${subTableFkclassName})
556
+#elseif($column.list && "" != $javaField)
557
+  obj.$column.javaField = ""
558
+#end
559
+#end
560
+  ${subclassName}List.value.push(obj)
561
+}
562
+
563
+/** ${subTable.functionName}删除按钮操作 */
564
+function handleDelete${subClassName}() {
565
+  if (checked${subClassName}.value.length == 0) {
566
+    proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
567
+  } else {
568
+    const ${subclassName}s = ${subclassName}List.value
569
+    const checked${subClassName}s = checked${subClassName}.value
570
+    ${subclassName}List.value = ${subclassName}s.filter(function(item) {
571
+      return checked${subClassName}s.indexOf(item.index) == -1
572
+    })
573
+  }
574
+}
575
+
576
+/** 复选框选中数据 */
577
+function handle${subClassName}SelectionChange(selection) {
578
+  checked${subClassName}.value = selection.map(item => item.index)
579
+}
580
+
581
+#end
582
+/** 导出按钮操作 */
583
+function handleExport() {
584
+  proxy.download('${moduleName}/${businessName}/export', {
585
+    ...queryParams.value
586
+  }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
587
+}
588
+
589
+getList()
590
+</script>

+ 140 - 0
airport-generator/src/main/resources/vm/xml/mapper.xml.vm

@@ -0,0 +1,140 @@
1
+<?xml version="1.0" encoding="UTF-8" ?>
2
+<!DOCTYPE mapper
3
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5
+<mapper namespace="${packageName}.mapper.${ClassName}Mapper">
6
+    
7
+    <resultMap type="${ClassName}" id="${ClassName}Result">
8
+#foreach ($column in $columns)
9
+        <result property="${column.javaField}"    column="${column.columnName}"    />
10
+#end
11
+    </resultMap>
12
+#if($table.sub)
13
+
14
+    <resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
15
+        <collection property="${subclassName}List" ofType="${subClassName}" column="${pkColumn.columnName}" select="select${subClassName}List" />
16
+    </resultMap>
17
+
18
+    <resultMap type="${subClassName}" id="${subClassName}Result">
19
+#foreach ($column in $subTable.columns)
20
+        <result property="${column.javaField}"    column="${column.columnName}"    />
21
+#end
22
+    </resultMap>
23
+#end
24
+
25
+    <sql id="select${ClassName}Vo">
26
+        select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName}
27
+    </sql>
28
+
29
+    <select id="select${ClassName}List" parameterType="${ClassName}" resultMap="${ClassName}Result">
30
+        <include refid="select${ClassName}Vo"/>
31
+        <where>  
32
+#foreach($column in $columns)
33
+#set($queryType=$column.queryType)
34
+#set($javaField=$column.javaField)
35
+#set($javaType=$column.javaType)
36
+#set($columnName=$column.columnName)
37
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
38
+#if($column.query)
39
+#if($column.queryType == "EQ")
40
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName = #{$javaField}</if>
41
+#elseif($queryType == "NE")
42
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName != #{$javaField}</if>
43
+#elseif($queryType == "GT")
44
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &gt; #{$javaField}</if>
45
+#elseif($queryType == "GTE")
46
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &gt;= #{$javaField}</if>
47
+#elseif($queryType == "LT")
48
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &lt; #{$javaField}</if>
49
+#elseif($queryType == "LTE")
50
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &lt;= #{$javaField}</if>
51
+#elseif($queryType == "LIKE")
52
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName like concat('%', #{$javaField}, '%')</if>
53
+#elseif($queryType == "BETWEEN")
54
+            <if test="params.begin$AttrName != null and params.begin$AttrName != '' and params.end$AttrName != null and params.end$AttrName != ''"> and $columnName between #{params.begin$AttrName} and #{params.end$AttrName}</if>
55
+#end
56
+#end
57
+#end
58
+        </where>
59
+    </select>
60
+    
61
+    <select id="select${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">
62
+#if($table.crud || $table.tree)
63
+        <include refid="select${ClassName}Vo"/>
64
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
65
+#elseif($table.sub)
66
+        select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end
67
+        from ${tableName}
68
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
69
+#end
70
+    </select>
71
+#if($table.sub)
72
+
73
+    <select id="select${subClassName}List" resultMap="${subClassName}Result">
74
+        select#foreach ($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
75
+        from ${subTableName}
76
+        where ${subTableFkName} = #{${subTableFkName}}
77
+    </select>
78
+#end
79
+
80
+    <insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
81
+        insert into ${tableName}
82
+        <trim prefix="(" suffix=")" suffixOverrides=",">
83
+#foreach($column in $columns)
84
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
85
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName,</if>
86
+#end
87
+#end
88
+         </trim>
89
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
90
+#foreach($column in $columns)
91
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
92
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">#{$column.javaField},</if>
93
+#end
94
+#end
95
+         </trim>
96
+    </insert>
97
+
98
+    <update id="update${ClassName}" parameterType="${ClassName}">
99
+        update ${tableName}
100
+        <trim prefix="SET" suffixOverrides=",">
101
+#foreach($column in $columns)
102
+#if($column.columnName != $pkColumn.columnName)
103
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName = #{$column.javaField},</if>
104
+#end
105
+#end
106
+        </trim>
107
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
108
+    </update>
109
+
110
+    <delete id="delete${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}">
111
+        delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
112
+    </delete>
113
+
114
+    <delete id="delete${ClassName}By${pkColumn.capJavaField}s" parameterType="String">
115
+        delete from ${tableName} where ${pkColumn.columnName} in 
116
+        <foreach item="${pkColumn.javaField}" collection="array" open="(" separator="," close=")">
117
+            #{${pkColumn.javaField}}
118
+        </foreach>
119
+    </delete>
120
+#if($table.sub)
121
+    
122
+    <delete id="delete${subClassName}By${subTableFkClassName}s" parameterType="String">
123
+        delete from ${subTableName} where ${subTableFkName} in 
124
+        <foreach item="${subTableFkclassName}" collection="array" open="(" separator="," close=")">
125
+            #{${subTableFkclassName}}
126
+        </foreach>
127
+    </delete>
128
+
129
+    <delete id="delete${subClassName}By${subTableFkClassName}" parameterType="${pkColumn.javaType}">
130
+        delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}}
131
+    </delete>
132
+
133
+    <insert id="batch${subClassName}">
134
+        insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values
135
+        <foreach item="item" index="index" collection="list" separator=",">
136
+            (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end)
137
+        </foreach>
138
+    </insert>
139
+#end
140
+</mapper>

+ 37 - 0
airport-item/pom.xml

@@ -0,0 +1,37 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <parent>
6
+        <groupId>com.sundot.airport</groupId>
7
+        <artifactId>airport</artifactId>
8
+        <version>3.9.0</version>
9
+    </parent>
10
+    <modelVersion>4.0.0</modelVersion>
11
+
12
+    <artifactId>airport-item</artifactId>
13
+
14
+    <description>
15
+        item查获物品管理模块
16
+    </description>
17
+
18
+    <dependencies>
19
+
20
+        <!-- 通用工具-->
21
+        <dependency>
22
+            <groupId>com.sundot.airport</groupId>
23
+            <artifactId>airport-common</artifactId>
24
+        </dependency>
25
+
26
+        <dependency>
27
+            <groupId>org.projectlombok</groupId>
28
+            <artifactId>lombok</artifactId>
29
+            <scope>provided</scope>
30
+        </dependency>
31
+        <dependency>
32
+            <groupId>com.sundot.airport</groupId>
33
+            <artifactId>airport-system</artifactId>
34
+        </dependency>
35
+
36
+    </dependencies>
37
+</project>

+ 50 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenChannelDto.java

@@ -0,0 +1,50 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.math.BigDecimal;
8
+
9
+/**
10
+ * 查获大屏:查获通道分布
11
+ *
12
+ * @author ruoyi
13
+ * @date 2025-07-25
14
+ */
15
+@Data
16
+public class ItemLargeScreenChannelDto implements Serializable {
17
+
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /**
21
+     * 通道编码
22
+     */
23
+    @Excel(name = "通道编码")
24
+    private String channelCode;
25
+
26
+    /**
27
+     * 通道名称
28
+     */
29
+    @Excel(name = "通道名称")
30
+    private String channelName;
31
+
32
+    /**
33
+     * 物品分类编码
34
+     */
35
+    @Excel(name = "物品分类编码")
36
+    private String categoryCode;
37
+
38
+    /**
39
+     * 物品分类名称
40
+     */
41
+    @Excel(name = "物品分类名称")
42
+    private String categoryName;
43
+
44
+    /**
45
+     * 总数
46
+     */
47
+    @Excel(name = "总数")
48
+    private BigDecimal total;
49
+
50
+}

+ 60 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenCommonDto.java

@@ -0,0 +1,60 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.math.BigDecimal;
8
+
9
+/**
10
+ * 查获大屏:查获排名/查获岗位分布/查获类别分布
11
+ *
12
+ * @author ruoyi
13
+ * @date 2025-07-25
14
+ */
15
+@Data
16
+public class ItemLargeScreenCommonDto implements Serializable {
17
+
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /**
21
+     * 主键ID
22
+     */
23
+    @Excel(name = "主键ID")
24
+    private Long id;
25
+
26
+    /**
27
+     * 编码
28
+     */
29
+    @Excel(name = "编码")
30
+    private String code;
31
+
32
+    /**
33
+     * 名称
34
+     */
35
+    @Excel(name = "名称")
36
+    private String name;
37
+
38
+    /**
39
+     * 总数
40
+     */
41
+    @Excel(name = "总数")
42
+    private BigDecimal total;
43
+
44
+    /**
45
+     * 比例
46
+     */
47
+    @Excel(name = "比例")
48
+    private BigDecimal scale;
49
+
50
+    /**
51
+     * 排名
52
+     */
53
+    private Integer rank;
54
+
55
+    /**
56
+     * 排名人数
57
+     */
58
+    private Integer rankCount;
59
+
60
+}

+ 36 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenDailyTrendDto.java

@@ -0,0 +1,36 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import cn.hutool.core.date.DatePattern;
4
+import com.fasterxml.jackson.annotation.JsonFormat;
5
+import com.sundot.airport.common.annotation.Excel;
6
+import lombok.Data;
7
+
8
+import java.io.Serializable;
9
+import java.math.BigDecimal;
10
+import java.util.Date;
11
+
12
+/**
13
+ * 查获大屏:查获趋势分布(按天)
14
+ *
15
+ * @author ruoyi
16
+ * @date 2025-11-10
17
+ */
18
+@Data
19
+public class ItemLargeScreenDailyTrendDto implements Serializable {
20
+
21
+    private static final long serialVersionUID = 1L;
22
+
23
+    /**
24
+     * 日期
25
+     */
26
+    @Excel(name = "日期")
27
+    @JsonFormat(pattern = "yyyy-MM-dd")
28
+    private Date date;
29
+
30
+    /**
31
+     * 查获总数量
32
+     */
33
+    @Excel(name = "查获总数量")
34
+    private BigDecimal total;
35
+
36
+}

+ 208 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenInfoDto.java

@@ -0,0 +1,208 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.fasterxml.jackson.annotation.JsonFormat;
4
+import com.sundot.airport.common.annotation.Excel;
5
+import lombok.Data;
6
+
7
+import java.io.Serializable;
8
+import java.math.BigDecimal;
9
+import java.util.Date;
10
+
11
+/**
12
+ * 查获大屏:移交公安情况/故意隐匿情况
13
+ *
14
+ * @author ruoyi
15
+ * @date 2025-07-25
16
+ */
17
+@Data
18
+public class ItemLargeScreenInfoDto implements Serializable {
19
+
20
+    private static final long serialVersionUID = 1L;
21
+
22
+    /**
23
+     * 查获记录ID
24
+     */
25
+    @Excel(name = "查获记录ID")
26
+    private Long mId;
27
+
28
+    /**
29
+     * 查获记录明细ID
30
+     */
31
+    @Excel(name = "查获记录明细ID")
32
+    private Long dId;
33
+
34
+    /**
35
+     * 检查人员ID
36
+     */
37
+    @Excel(name = "检查人员ID")
38
+    private Long inspectUserId;
39
+
40
+    /**
41
+     * 检查人员名称
42
+     */
43
+    @Excel(name = "检查人员名称")
44
+    private String inspectUserName;
45
+
46
+    /**
47
+     * 查获时间
48
+     */
49
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
50
+    @Excel(name = "查获时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
51
+    private Date seizureTime;
52
+
53
+    /**
54
+     * 航站楼编码
55
+     */
56
+    @Excel(name = "航站楼编码")
57
+    private Long terminlCode;
58
+
59
+    /**
60
+     * 航站楼名称
61
+     */
62
+    @Excel(name = "航站楼名称")
63
+    private String terminlName;
64
+
65
+    /**
66
+     * 区域编码
67
+     */
68
+    @Excel(name = "区域编码")
69
+    private Long regionalCode;
70
+
71
+    /**
72
+     * 区域名称
73
+     */
74
+    @Excel(name = "区域名称")
75
+    private String regionalName;
76
+
77
+    /**
78
+     * 通道编码
79
+     */
80
+    @Excel(name = "通道编码")
81
+    private String channelCode;
82
+
83
+    /**
84
+     * 通道名称
85
+     */
86
+    @Excel(name = "通道名称")
87
+    private String channelName;
88
+
89
+    /**
90
+     * 检查岗位
91
+     */
92
+    @Excel(name = "检查岗位")
93
+    private String checkMethod;
94
+
95
+    /**
96
+     * 检查岗位名称
97
+     */
98
+    @Excel(name = "检查岗位名称")
99
+    private String checkMethodDesc;
100
+
101
+
102
+    /**
103
+     * 物品分类编码1级
104
+     */
105
+    @Excel(name = "物品分类编码1级")
106
+    private String categoryCodeOne;
107
+
108
+    /**
109
+     * 物品分类名称1级
110
+     */
111
+    @Excel(name = "物品分类名称1级")
112
+    private String categoryNameOne;
113
+
114
+    /**
115
+     * 物品分类编码2级
116
+     */
117
+    @Excel(name = "物品分类编码2级")
118
+    private String categoryCodeTwo;
119
+
120
+    /**
121
+     * 物品分类名称2级
122
+     */
123
+    @Excel(name = "物品分类名称2级")
124
+    private String categoryNameTwo;
125
+
126
+    /**
127
+     * 物品编码
128
+     */
129
+    @Excel(name = "物品编码")
130
+    private String itemCode;
131
+
132
+    /**
133
+     * 物品名称
134
+     */
135
+    @Excel(name = "物品名称")
136
+    private String itemName;
137
+
138
+    /**
139
+     * 数量
140
+     */
141
+    @Excel(name = "数量")
142
+    private BigDecimal quantity;
143
+
144
+    /**
145
+     * 单位
146
+     */
147
+    @Excel(name = "单位")
148
+    private String unit;
149
+
150
+    /**
151
+     * 单位名称
152
+     */
153
+    @Excel(name = "单位名称")
154
+    private String unitDesc;
155
+
156
+    /**
157
+     * 处理方式
158
+     */
159
+    @Excel(name = "处理方式")
160
+    private String handlingMethod;
161
+
162
+    /**
163
+     * 处理方式名称
164
+     */
165
+    @Excel(name = "处理方式名称")
166
+    private String handlingMethodDesc;
167
+
168
+    /**
169
+     * 是否故意隐匿(1-是,0-否)
170
+     */
171
+    @Excel(name = "是否故意隐匿(1-是,0-否)")
172
+    private Long isActiveConcealment;
173
+    /**
174
+     * 检查部位编码1级
175
+     */
176
+    @Excel(name = "检查部位编码1级")
177
+    private String checkPositionCodeOne;
178
+
179
+    /**
180
+     * 检查部位名称1级
181
+     */
182
+    @Excel(name = "检查部位名称1级")
183
+    private String checkPositionNameOne;
184
+
185
+    /**
186
+     * 检查部位编码2级
187
+     */
188
+    @Excel(name = "检查部位编码2级")
189
+    private String checkPositionCodeTwo;
190
+
191
+    /**
192
+     * 检查部位名称2级
193
+     */
194
+    @Excel(name = "检查部位名称2级")
195
+    private String checkPositionNameTwo;
196
+
197
+    /**
198
+     * 具体位置
199
+     */
200
+    @Excel(name = "具体位置")
201
+    private String checkPositionSpecific;
202
+
203
+    /**
204
+     * 用户名称
205
+     */
206
+    private String nackName;
207
+
208
+}

+ 28 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenPositionAppDto.java

@@ -0,0 +1,28 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+
8
+@Data
9
+public class ItemLargeScreenPositionAppDto {
10
+
11
+    /**
12
+     * 编码
13
+     */
14
+    @Excel(name = "编码")
15
+    private String code;
16
+
17
+    /**
18
+     * 名称
19
+     */
20
+    @Excel(name = "名称")
21
+    private String name;
22
+
23
+    /**
24
+     * 总数
25
+     */
26
+    @Excel(name = "总数")
27
+    private BigDecimal total;
28
+}

+ 50 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenPositionDto.java

@@ -0,0 +1,50 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.math.BigDecimal;
8
+
9
+/**
10
+ * 查获大屏:查获位置分布
11
+ *
12
+ * @author ruoyi
13
+ * @date 2025-07-25
14
+ */
15
+@Data
16
+public class ItemLargeScreenPositionDto implements Serializable {
17
+
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /**
21
+     * 检查部位编码1级
22
+     */
23
+    @Excel(name = "检查部位编码1级")
24
+    private String checkPositionCodeOne;
25
+
26
+    /**
27
+     * 检查部位名称1级
28
+     */
29
+    @Excel(name = "检查部位名称1级")
30
+    private String checkPositionNameOne;
31
+
32
+    /**
33
+     * 检查部位编码2级
34
+     */
35
+    @Excel(name = "检查部位编码2级")
36
+    private String checkPositionCodeTwo;
37
+
38
+    /**
39
+     * 检查部位名称2级
40
+     */
41
+    @Excel(name = "检查部位名称2级")
42
+    private String checkPositionNameTwo;
43
+
44
+    /**
45
+     * 总数
46
+     */
47
+    @Excel(name = "总数")
48
+    private BigDecimal total;
49
+
50
+}

+ 53 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenStatsDto.java

@@ -0,0 +1,53 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.math.BigDecimal;
8
+
9
+/**
10
+ * 查获大屏统计结果DTO
11
+ *
12
+ * @author ruoyi
13
+ * @date 2025-10-24
14
+ */
15
+@Data
16
+public class ItemLargeScreenStatsDto implements Serializable {
17
+
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /**
21
+     * 统计维度
22
+     */
23
+    @Excel(name = "统计维度")
24
+    private String dimension;
25
+
26
+    /**
27
+     * 有效查获总数
28
+     */
29
+    @Excel(name = "有效查获总数")
30
+    private BigDecimal effectiveSeizureCount;
31
+
32
+    /**
33
+     * 移交公安总数
34
+     */
35
+    @Excel(name = "移交公安总数")
36
+    private BigDecimal policeTotal;
37
+
38
+    /**
39
+     * 故意隐匿总数
40
+     */
41
+    @Excel(name = "故意隐匿总数")
42
+    private BigDecimal concealTotal;
43
+
44
+    /**
45
+     * 部门ID
46
+     */
47
+    private Long deptId;
48
+
49
+    /**
50
+     * 部门名称
51
+     */
52
+    private String deptName;
53
+}

+ 32 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenTimeSpanDto.java

@@ -0,0 +1,32 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.math.BigDecimal;
8
+
9
+/**
10
+ * 查获大屏:查获时段分布
11
+ *
12
+ * @author ruoyi
13
+ * @date 2025-07-25
14
+ */
15
+@Data
16
+public class ItemLargeScreenTimeSpanDto implements Serializable {
17
+
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /**
21
+     * 时段
22
+     */
23
+    @Excel(name = "时段")
24
+    private String hourOfDay;
25
+
26
+    /**
27
+     * 查获总数量
28
+     */
29
+    @Excel(name = "查获总数量")
30
+    private BigDecimal total;
31
+
32
+}

+ 56 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenTotalSomeDto.java

@@ -0,0 +1,56 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.math.BigDecimal;
8
+
9
+/**
10
+ * 查获大屏:查获总数量+移交公安数量+故意隐匿数量
11
+ *
12
+ * @author ruoyi
13
+ * @date 2025-07-25
14
+ */
15
+@Data
16
+public class ItemLargeScreenTotalSomeDto implements Serializable {
17
+
18
+    private static final long serialVersionUID = 1L;
19
+
20
+    /**
21
+     * 查获总数量
22
+     */
23
+    @Excel(name = "查获总数量")
24
+    private BigDecimal total;
25
+
26
+    /**
27
+     * 移交公安数量
28
+     */
29
+    @Excel(name = "移交公安数量")
30
+    private BigDecimal policeTotal;
31
+
32
+    /**
33
+     * 故意隐匿数量
34
+     */
35
+    @Excel(name = "故意隐匿数量")
36
+    private BigDecimal concealTotal;
37
+
38
+    /**
39
+     * 查获总数量-前一天
40
+     */
41
+    @Excel(name = "查获总数量-前一天")
42
+    private BigDecimal totalBefore;
43
+
44
+    /**
45
+     * 移交公安数量-前一天
46
+     */
47
+    @Excel(name = "移交公安数量-前一天")
48
+    private BigDecimal policeTotalBefore;
49
+
50
+    /**
51
+     * 故意隐匿数量-前一天
52
+     */
53
+    @Excel(name = "故意隐匿数量-前一天")
54
+    private BigDecimal concealTotalBefore;
55
+
56
+}

+ 71 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureCount.java

@@ -0,0 +1,71 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import java.math.BigDecimal;
4
+
5
+/**
6
+ * 查获物品分类数量
7
+ */
8
+public class ItemSeizureCount {
9
+    private static final long serialVersionUID = 1L;
10
+
11
+    /**
12
+     * 分类ID
13
+     */
14
+    private Long categoryId;
15
+    /**
16
+     * 分类编码
17
+     */
18
+    private String categoryCode;
19
+    /**
20
+     * 分类名称
21
+     */
22
+    private String categoryName;
23
+
24
+    /**
25
+     * 分类数量
26
+     */
27
+    private BigDecimal categoryCount;
28
+
29
+    public Long getCategoryId() {
30
+        return categoryId;
31
+    }
32
+
33
+    public void setCategoryId(Long categoryId) {
34
+        this.categoryId = categoryId;
35
+    }
36
+
37
+    public String getCategoryCode() {
38
+        return categoryCode;
39
+    }
40
+
41
+    public void setCategoryCode(String categoryCode) {
42
+        this.categoryCode = categoryCode;
43
+    }
44
+
45
+    public String getCategoryName() {
46
+        return categoryName;
47
+    }
48
+
49
+    public void setCategoryName(String categoryName) {
50
+        this.categoryName = categoryName;
51
+    }
52
+
53
+    public BigDecimal getCategoryCount() {
54
+        return categoryCount;
55
+    }
56
+
57
+    public void setCategoryCount(BigDecimal categoryCount) {
58
+        this.categoryCount = categoryCount;
59
+    }
60
+
61
+    @Override
62
+    public String toString() {
63
+        return "ItemSeizureConut{" +
64
+                "categoryId=" + categoryId +
65
+                ", categoryCode='" + categoryCode + '\'' +
66
+                ", categoryName='" + categoryName + '\'' +
67
+                ", categoryCount=" + categoryCount +
68
+                '}';
69
+    }
70
+
71
+}

+ 786 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureDto.java

@@ -0,0 +1,786 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import com.fasterxml.jackson.annotation.JsonFormat;
4
+import com.sundot.airport.common.annotation.Excel;
5
+
6
+import java.math.BigDecimal;
7
+import java.util.Date;
8
+
9
+/**
10
+ * 查获物品明细对象
11
+ */
12
+public class ItemSeizureDto {
13
+    private static final long serialVersionUID = 1L;
14
+
15
+    /**
16
+     * 检查人员ID
17
+     */
18
+    @Excel(name = "检查人员ID")
19
+    private Long inspectUserId;
20
+
21
+    /**
22
+     * 通道编码
23
+     */
24
+    @Excel(name = "通道编码")
25
+    private String channelCode;
26
+
27
+    /**
28
+     * 查获时间
29
+     */
30
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
31
+    @Excel(name = "查获时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
32
+    private Date seizureTime;
33
+
34
+    /**
35
+     * 检查岗位
36
+     */
37
+    @Excel(name = "检查岗位")
38
+    private String checkMethod;
39
+
40
+    /**
41
+     * 考勤记录ID
42
+     */
43
+    @Excel(name = "考勤记录ID")
44
+    private Long attendanceId;
45
+
46
+    /**
47
+     * 考勤班组ID
48
+     */
49
+    @Excel(name = "考勤班组ID")
50
+    private Long attendanceTeamId;
51
+
52
+    /**
53
+     * 考勤班组名称
54
+     */
55
+    @Excel(name = "考勤班组名称")
56
+    private String attendanceTeamName;
57
+
58
+    /**
59
+     * 考勤科室ID
60
+     */
61
+    @Excel(name = "考勤科室ID")
62
+    private Long attendanceDepartmentId;
63
+
64
+    /**
65
+     * 考勤科室名称
66
+     */
67
+    @Excel(name = "考勤科室名称")
68
+    private String attendanceDepartmentName;
69
+
70
+    /**
71
+     * 考勤机构站ID
72
+     */
73
+    @Excel(name = "考勤机构站ID")
74
+    private Long attendanceStationId;
75
+
76
+    /**
77
+     * 考勤机构站名称
78
+     */
79
+    @Excel(name = "考勤机构站名称")
80
+    private String attendanceStationName;
81
+
82
+    /**
83
+     * 通道名称
84
+     */
85
+    @Excel(name = "通道名称")
86
+    private String channelName;
87
+
88
+    /**
89
+     * 区域编码
90
+     */
91
+    @Excel(name = "区域编码")
92
+    private Long regionalCode;
93
+
94
+    /**
95
+     * 区域名称
96
+     */
97
+    @Excel(name = "区域名称")
98
+    private String regionalName;
99
+
100
+    /**
101
+     * 航站楼编码
102
+     */
103
+    @Excel(name = "航站楼编码")
104
+    private Long terminlCode;
105
+
106
+    /**
107
+     * 航站楼名称
108
+     */
109
+    @Excel(name = "航站楼名称")
110
+    private String terminlName;
111
+
112
+    /**
113
+     * 旅客姓名
114
+     */
115
+    @Excel(name = "旅客姓名")
116
+    private String passengerName;
117
+
118
+    /**
119
+     * 旅客性别
120
+     */
121
+    @Excel(name = "旅客性别")
122
+    private String passengerGender;
123
+
124
+    /**
125
+     * 旅客身份证号
126
+     */
127
+    @Excel(name = "旅客身份证号")
128
+    private String passengerCard;
129
+
130
+    /**
131
+     * 航班号
132
+     */
133
+    @Excel(name = "航班号")
134
+    private String passengerFlight;
135
+
136
+    /**
137
+     * 查获人班组ID
138
+     */
139
+    @Excel(name = "查获人班组ID")
140
+    private Long inspectTeamId;
141
+
142
+    /**
143
+     * 查获人班组名称
144
+     */
145
+    @Excel(name = "查获人班组名称")
146
+    private String inspectTeamName;
147
+
148
+    /**
149
+     * 查获人科室ID
150
+     */
151
+    @Excel(name = "查获人科室ID")
152
+    private Long inspectDepartmentId;
153
+
154
+    /**
155
+     * 查获人科室名称
156
+     */
157
+    @Excel(name = "查获人科室名称")
158
+    private String inspectDepartmentName;
159
+
160
+    /**
161
+     * 查获人机构站ID
162
+     */
163
+    @Excel(name = "查获人机构站ID")
164
+    private Long inspectStationId;
165
+
166
+    /**
167
+     * 查获人机构站名称
168
+     */
169
+    @Excel(name = "查获人机构站名称")
170
+    private String inspectStationName;
171
+
172
+    /**
173
+     * 检查岗位名称
174
+     */
175
+    @Excel(name = "检查岗位名称")
176
+    private String checkMethodDesc;
177
+
178
+    /**
179
+     * 旅客性别名称
180
+     */
181
+    @Excel(name = "旅客性别名称")
182
+    private String passengerGenderDesc;
183
+
184
+    /**
185
+     * 检查人员名称
186
+     */
187
+    @Excel(name = "检查人员名称")
188
+    private String inspectUserName;
189
+
190
+
191
+    /**
192
+     * 主键
193
+     */
194
+    private Long id;
195
+
196
+    /**
197
+     * 查获记录ID
198
+     */
199
+    @Excel(name = "查获记录ID")
200
+    private Long recordId;
201
+
202
+    /**
203
+     * 物品编码
204
+     */
205
+    @Excel(name = "物品编码")
206
+    private String itemCode;
207
+
208
+    /**
209
+     * 数量
210
+     */
211
+    @Excel(name = "数量")
212
+    private BigDecimal quantity;
213
+
214
+    /**
215
+     * 检查部位编码1级
216
+     */
217
+    @Excel(name = "检查部位编码1级")
218
+    private String checkPositionCodeOne;
219
+
220
+    /**
221
+     * 是否故意隐匿(1-是,0-否)
222
+     */
223
+    @Excel(name = "是否故意隐匿(1-是,0-否)")
224
+    private Long isActiveConcealment;
225
+
226
+    /**
227
+     * 检查部位编码2级
228
+     */
229
+    @Excel(name = "检查部位编码2级")
230
+    private String checkPositionCodeTwo;
231
+
232
+    /**
233
+     * 具体位置
234
+     */
235
+    @Excel(name = "具体位置")
236
+    private String checkPositionSpecific;
237
+
238
+    /**
239
+     * 物品名称
240
+     */
241
+    @Excel(name = "物品名称")
242
+    private String itemName;
243
+
244
+    /**
245
+     * 物品分类编码1级
246
+     */
247
+    @Excel(name = "物品分类编码1级")
248
+    private String categoryCodeOne;
249
+
250
+    /**
251
+     * 物品分类名称1级
252
+     */
253
+    @Excel(name = "物品分类名称1级")
254
+    private String categoryNameOne;
255
+
256
+    /**
257
+     * 物品分类编码2级
258
+     */
259
+    @Excel(name = "物品分类编码2级")
260
+    private String categoryCodeTwo;
261
+
262
+    /**
263
+     * 物品分类名称2级
264
+     */
265
+    @Excel(name = "物品分类名称2级")
266
+    private String categoryNameTwo;
267
+
268
+    /**
269
+     * 单位
270
+     */
271
+    @Excel(name = "单位")
272
+    private String unit;
273
+
274
+    /**
275
+     * 检查部位名称1级
276
+     */
277
+    @Excel(name = "检查部位名称1级")
278
+    private String checkPositionNameOne;
279
+
280
+    /**
281
+     * 检查部位名称2级
282
+     */
283
+    @Excel(name = "检查部位名称2级")
284
+    private String checkPositionNameTwo;
285
+
286
+    /**
287
+     * 单位名称
288
+     */
289
+    @Excel(name = "单位名称")
290
+    private String unitDesc;
291
+
292
+    /**
293
+     * 处理方式
294
+     */
295
+    @Excel(name = "处理方式")
296
+    private String handlingMethod;
297
+
298
+    /**
299
+     * 处理方式名称
300
+     */
301
+    @Excel(name = "处理方式名称")
302
+    private String handlingMethodDesc;
303
+
304
+    /**
305
+     * 附件ID
306
+     */
307
+    @Excel(name = "附件ID")
308
+    private String attachmentId;
309
+
310
+    /**
311
+     * 附件URL
312
+     */
313
+    @Excel(name = "附件URL")
314
+    private String attachmentUrl;
315
+
316
+    /**
317
+     * 附件名称
318
+     */
319
+    @Excel(name = "附件名称")
320
+    private String attachmentName;
321
+
322
+    public Long getInspectUserId() {
323
+        return inspectUserId;
324
+    }
325
+
326
+    public void setInspectUserId(Long inspectUserId) {
327
+        this.inspectUserId = inspectUserId;
328
+    }
329
+
330
+    public String getChannelCode() {
331
+        return channelCode;
332
+    }
333
+
334
+    public void setChannelCode(String channelCode) {
335
+        this.channelCode = channelCode;
336
+    }
337
+
338
+    public Date getSeizureTime() {
339
+        return seizureTime;
340
+    }
341
+
342
+    public void setSeizureTime(Date seizureTime) {
343
+        this.seizureTime = seizureTime;
344
+    }
345
+
346
+    public String getCheckMethod() {
347
+        return checkMethod;
348
+    }
349
+
350
+    public void setCheckMethod(String checkMethod) {
351
+        this.checkMethod = checkMethod;
352
+    }
353
+
354
+    public Long getAttendanceId() {
355
+        return attendanceId;
356
+    }
357
+
358
+    public void setAttendanceId(Long attendanceId) {
359
+        this.attendanceId = attendanceId;
360
+    }
361
+
362
+    public Long getAttendanceTeamId() {
363
+        return attendanceTeamId;
364
+    }
365
+
366
+    public void setAttendanceTeamId(Long attendanceTeamId) {
367
+        this.attendanceTeamId = attendanceTeamId;
368
+    }
369
+
370
+    public String getAttendanceTeamName() {
371
+        return attendanceTeamName;
372
+    }
373
+
374
+    public void setAttendanceTeamName(String attendanceTeamName) {
375
+        this.attendanceTeamName = attendanceTeamName;
376
+    }
377
+
378
+    public Long getAttendanceDepartmentId() {
379
+        return attendanceDepartmentId;
380
+    }
381
+
382
+    public void setAttendanceDepartmentId(Long attendanceDepartmentId) {
383
+        this.attendanceDepartmentId = attendanceDepartmentId;
384
+    }
385
+
386
+    public String getAttendanceDepartmentName() {
387
+        return attendanceDepartmentName;
388
+    }
389
+
390
+    public void setAttendanceDepartmentName(String attendanceDepartmentName) {
391
+        this.attendanceDepartmentName = attendanceDepartmentName;
392
+    }
393
+
394
+    public Long getAttendanceStationId() {
395
+        return attendanceStationId;
396
+    }
397
+
398
+    public void setAttendanceStationId(Long attendanceStationId) {
399
+        this.attendanceStationId = attendanceStationId;
400
+    }
401
+
402
+    public String getAttendanceStationName() {
403
+        return attendanceStationName;
404
+    }
405
+
406
+    public void setAttendanceStationName(String attendanceStationName) {
407
+        this.attendanceStationName = attendanceStationName;
408
+    }
409
+
410
+    public String getChannelName() {
411
+        return channelName;
412
+    }
413
+
414
+    public void setChannelName(String channelName) {
415
+        this.channelName = channelName;
416
+    }
417
+
418
+    public Long getRegionalCode() {
419
+        return regionalCode;
420
+    }
421
+
422
+    public void setRegionalCode(Long regionalCode) {
423
+        this.regionalCode = regionalCode;
424
+    }
425
+
426
+    public String getRegionalName() {
427
+        return regionalName;
428
+    }
429
+
430
+    public void setRegionalName(String regionalName) {
431
+        this.regionalName = regionalName;
432
+    }
433
+
434
+    public Long getTerminlCode() {
435
+        return terminlCode;
436
+    }
437
+
438
+    public void setTerminlCode(Long terminlCode) {
439
+        this.terminlCode = terminlCode;
440
+    }
441
+
442
+    public String getTerminlName() {
443
+        return terminlName;
444
+    }
445
+
446
+    public void setTerminlName(String terminlName) {
447
+        this.terminlName = terminlName;
448
+    }
449
+
450
+    public String getPassengerName() {
451
+        return passengerName;
452
+    }
453
+
454
+    public void setPassengerName(String passengerName) {
455
+        this.passengerName = passengerName;
456
+    }
457
+
458
+    public String getPassengerGender() {
459
+        return passengerGender;
460
+    }
461
+
462
+    public void setPassengerGender(String passengerGender) {
463
+        this.passengerGender = passengerGender;
464
+    }
465
+
466
+    public String getPassengerCard() {
467
+        return passengerCard;
468
+    }
469
+
470
+    public void setPassengerCard(String passengerCard) {
471
+        this.passengerCard = passengerCard;
472
+    }
473
+
474
+    public String getPassengerFlight() {
475
+        return passengerFlight;
476
+    }
477
+
478
+    public void setPassengerFlight(String passengerFlight) {
479
+        this.passengerFlight = passengerFlight;
480
+    }
481
+
482
+    public Long getInspectTeamId() {
483
+        return inspectTeamId;
484
+    }
485
+
486
+    public void setInspectTeamId(Long inspectTeamId) {
487
+        this.inspectTeamId = inspectTeamId;
488
+    }
489
+
490
+    public String getInspectTeamName() {
491
+        return inspectTeamName;
492
+    }
493
+
494
+    public void setInspectTeamName(String inspectTeamName) {
495
+        this.inspectTeamName = inspectTeamName;
496
+    }
497
+
498
+    public Long getInspectDepartmentId() {
499
+        return inspectDepartmentId;
500
+    }
501
+
502
+    public void setInspectDepartmentId(Long inspectDepartmentId) {
503
+        this.inspectDepartmentId = inspectDepartmentId;
504
+    }
505
+
506
+    public String getInspectDepartmentName() {
507
+        return inspectDepartmentName;
508
+    }
509
+
510
+    public void setInspectDepartmentName(String inspectDepartmentName) {
511
+        this.inspectDepartmentName = inspectDepartmentName;
512
+    }
513
+
514
+    public Long getInspectStationId() {
515
+        return inspectStationId;
516
+    }
517
+
518
+    public void setInspectStationId(Long inspectStationId) {
519
+        this.inspectStationId = inspectStationId;
520
+    }
521
+
522
+    public String getInspectStationName() {
523
+        return inspectStationName;
524
+    }
525
+
526
+    public void setInspectStationName(String inspectStationName) {
527
+        this.inspectStationName = inspectStationName;
528
+    }
529
+
530
+    public String getCheckMethodDesc() {
531
+        return checkMethodDesc;
532
+    }
533
+
534
+    public void setCheckMethodDesc(String checkMethodDesc) {
535
+        this.checkMethodDesc = checkMethodDesc;
536
+    }
537
+
538
+    public String getPassengerGenderDesc() {
539
+        return passengerGenderDesc;
540
+    }
541
+
542
+    public void setPassengerGenderDesc(String passengerGenderDesc) {
543
+        this.passengerGenderDesc = passengerGenderDesc;
544
+    }
545
+
546
+    public String getInspectUserName() {
547
+        return inspectUserName;
548
+    }
549
+
550
+    public void setInspectUserName(String inspectUserName) {
551
+        this.inspectUserName = inspectUserName;
552
+    }
553
+
554
+    public Long getId() {
555
+        return id;
556
+    }
557
+
558
+    public void setId(Long id) {
559
+        this.id = id;
560
+    }
561
+
562
+    public Long getRecordId() {
563
+        return recordId;
564
+    }
565
+
566
+    public void setRecordId(Long recordId) {
567
+        this.recordId = recordId;
568
+    }
569
+
570
+    public String getItemCode() {
571
+        return itemCode;
572
+    }
573
+
574
+    public void setItemCode(String itemCode) {
575
+        this.itemCode = itemCode;
576
+    }
577
+
578
+    public BigDecimal getQuantity() {
579
+        return quantity;
580
+    }
581
+
582
+    public void setQuantity(BigDecimal quantity) {
583
+        this.quantity = quantity;
584
+    }
585
+
586
+    public String getCheckPositionCodeOne() {
587
+        return checkPositionCodeOne;
588
+    }
589
+
590
+    public void setCheckPositionCodeOne(String checkPositionCodeOne) {
591
+        this.checkPositionCodeOne = checkPositionCodeOne;
592
+    }
593
+
594
+    public Long getIsActiveConcealment() {
595
+        return isActiveConcealment;
596
+    }
597
+
598
+    public void setIsActiveConcealment(Long isActiveConcealment) {
599
+        this.isActiveConcealment = isActiveConcealment;
600
+    }
601
+
602
+    public String getCheckPositionCodeTwo() {
603
+        return checkPositionCodeTwo;
604
+    }
605
+
606
+    public void setCheckPositionCodeTwo(String checkPositionCodeTwo) {
607
+        this.checkPositionCodeTwo = checkPositionCodeTwo;
608
+    }
609
+
610
+    public String getCheckPositionSpecific() {
611
+        return checkPositionSpecific;
612
+    }
613
+
614
+    public void setCheckPositionSpecific(String checkPositionSpecific) {
615
+        this.checkPositionSpecific = checkPositionSpecific;
616
+    }
617
+
618
+    public String getItemName() {
619
+        return itemName;
620
+    }
621
+
622
+    public void setItemName(String itemName) {
623
+        this.itemName = itemName;
624
+    }
625
+
626
+    public String getCategoryCodeOne() {
627
+        return categoryCodeOne;
628
+    }
629
+
630
+    public void setCategoryCodeOne(String categoryCodeOne) {
631
+        this.categoryCodeOne = categoryCodeOne;
632
+    }
633
+
634
+    public String getCategoryNameOne() {
635
+        return categoryNameOne;
636
+    }
637
+
638
+    public void setCategoryNameOne(String categoryNameOne) {
639
+        this.categoryNameOne = categoryNameOne;
640
+    }
641
+
642
+    public String getCategoryCodeTwo() {
643
+        return categoryCodeTwo;
644
+    }
645
+
646
+    public void setCategoryCodeTwo(String categoryCodeTwo) {
647
+        this.categoryCodeTwo = categoryCodeTwo;
648
+    }
649
+
650
+    public String getCategoryNameTwo() {
651
+        return categoryNameTwo;
652
+    }
653
+
654
+    public void setCategoryNameTwo(String categoryNameTwo) {
655
+        this.categoryNameTwo = categoryNameTwo;
656
+    }
657
+
658
+    public String getUnit() {
659
+        return unit;
660
+    }
661
+
662
+    public void setUnit(String unit) {
663
+        this.unit = unit;
664
+    }
665
+
666
+    public String getCheckPositionNameOne() {
667
+        return checkPositionNameOne;
668
+    }
669
+
670
+    public void setCheckPositionNameOne(String checkPositionNameOne) {
671
+        this.checkPositionNameOne = checkPositionNameOne;
672
+    }
673
+
674
+    public String getCheckPositionNameTwo() {
675
+        return checkPositionNameTwo;
676
+    }
677
+
678
+    public void setCheckPositionNameTwo(String checkPositionNameTwo) {
679
+        this.checkPositionNameTwo = checkPositionNameTwo;
680
+    }
681
+
682
+    public String getUnitDesc() {
683
+        return unitDesc;
684
+    }
685
+
686
+    public void setUnitDesc(String unitDesc) {
687
+        this.unitDesc = unitDesc;
688
+    }
689
+
690
+    public String getHandlingMethod() {
691
+        return handlingMethod;
692
+    }
693
+
694
+    public void setHandlingMethod(String handlingMethod) {
695
+        this.handlingMethod = handlingMethod;
696
+    }
697
+
698
+    public String getHandlingMethodDesc() {
699
+        return handlingMethodDesc;
700
+    }
701
+
702
+    public void setHandlingMethodDesc(String handlingMethodDesc) {
703
+        this.handlingMethodDesc = handlingMethodDesc;
704
+    }
705
+
706
+    public String getAttachmentId() {
707
+        return attachmentId;
708
+    }
709
+
710
+    public void setAttachmentId(String attachmentId) {
711
+        this.attachmentId = attachmentId;
712
+    }
713
+
714
+    public String getAttachmentUrl() {
715
+        return attachmentUrl;
716
+    }
717
+
718
+    public void setAttachmentUrl(String attachmentUrl) {
719
+        this.attachmentUrl = attachmentUrl;
720
+    }
721
+
722
+    public String getAttachmentName() {
723
+        return attachmentName;
724
+    }
725
+
726
+    public void setAttachmentName(String attachmentName) {
727
+        this.attachmentName = attachmentName;
728
+    }
729
+
730
+    @Override
731
+    public String toString() {
732
+        return "ItemSeizureDto{" +
733
+                "inspectUserId=" + inspectUserId +
734
+                ", channelCode='" + channelCode + '\'' +
735
+                ", seizureTime=" + seizureTime +
736
+                ", checkMethod='" + checkMethod + '\'' +
737
+                ", attendanceId=" + attendanceId +
738
+                ", attendanceTeamId=" + attendanceTeamId +
739
+                ", attendanceTeamName='" + attendanceTeamName + '\'' +
740
+                ", attendanceDepartmentId=" + attendanceDepartmentId +
741
+                ", attendanceDepartmentName='" + attendanceDepartmentName + '\'' +
742
+                ", attendanceStationId=" + attendanceStationId +
743
+                ", attendanceStationName='" + attendanceStationName + '\'' +
744
+                ", channelName='" + channelName + '\'' +
745
+                ", regionalCode=" + regionalCode +
746
+                ", regionalName='" + regionalName + '\'' +
747
+                ", terminlCode=" + terminlCode +
748
+                ", terminlName='" + terminlName + '\'' +
749
+                ", passengerName='" + passengerName + '\'' +
750
+                ", passengerGender='" + passengerGender + '\'' +
751
+                ", passengerCard='" + passengerCard + '\'' +
752
+                ", passengerFlight='" + passengerFlight + '\'' +
753
+                ", inspectTeamId=" + inspectTeamId +
754
+                ", inspectTeamName='" + inspectTeamName + '\'' +
755
+                ", inspectDepartmentId=" + inspectDepartmentId +
756
+                ", inspectDepartmentName='" + inspectDepartmentName + '\'' +
757
+                ", inspectStationId=" + inspectStationId +
758
+                ", inspectStationName='" + inspectStationName + '\'' +
759
+                ", checkMethodDesc='" + checkMethodDesc + '\'' +
760
+                ", passengerGenderDesc='" + passengerGenderDesc + '\'' +
761
+                ", inspectUserName='" + inspectUserName + '\'' +
762
+                ", id=" + id +
763
+                ", recordId=" + recordId +
764
+                ", itemCode='" + itemCode + '\'' +
765
+                ", quantity=" + quantity +
766
+                ", checkPositionCodeOne='" + checkPositionCodeOne + '\'' +
767
+                ", isActiveConcealment=" + isActiveConcealment +
768
+                ", checkPositionCodeTwo='" + checkPositionCodeTwo + '\'' +
769
+                ", checkPositionSpecific='" + checkPositionSpecific + '\'' +
770
+                ", itemName='" + itemName + '\'' +
771
+                ", categoryCodeOne='" + categoryCodeOne + '\'' +
772
+                ", categoryNameOne='" + categoryNameOne + '\'' +
773
+                ", categoryCodeTwo='" + categoryCodeTwo + '\'' +
774
+                ", categoryNameTwo='" + categoryNameTwo + '\'' +
775
+                ", unit='" + unit + '\'' +
776
+                ", checkPositionNameOne='" + checkPositionNameOne + '\'' +
777
+                ", checkPositionNameTwo='" + checkPositionNameTwo + '\'' +
778
+                ", unitDesc='" + unitDesc + '\'' +
779
+                ", handlingMethod='" + handlingMethod + '\'' +
780
+                ", handlingMethodDesc='" + handlingMethodDesc + '\'' +
781
+                ", attachmentId='" + attachmentId + '\'' +
782
+                ", attachmentUrl='" + attachmentUrl + '\'' +
783
+                ", attachmentName='" + attachmentName + '\'' +
784
+                '}';
785
+    }
786
+}

+ 435 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureItems.java

@@ -0,0 +1,435 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import java.math.BigDecimal;
4
+import java.util.List;
5
+
6
+import com.baomidou.mybatisplus.annotation.IdType;
7
+import com.baomidou.mybatisplus.annotation.TableId;
8
+import com.baomidou.mybatisplus.annotation.TableName;
9
+import com.sundot.airport.common.domain.BaseAttachment;
10
+import org.apache.commons.lang3.builder.ToStringBuilder;
11
+import org.apache.commons.lang3.builder.ToStringStyle;
12
+import com.sundot.airport.common.annotation.Excel;
13
+import com.sundot.airport.common.core.domain.BaseEntity;
14
+
15
+/**
16
+ * 查获物品明细对象 item_seizure_items
17
+ *
18
+ * @author ruoyi
19
+ * @date 2025-07-10
20
+ */
21
+@TableName("item_seizure_items")
22
+public class ItemSeizureItems extends BaseEntity {
23
+    private static final long serialVersionUID = 1L;
24
+
25
+    /**
26
+     * 租户号
27
+     */
28
+    private String tenantId;
29
+
30
+    /**
31
+     * 乐观锁
32
+     */
33
+    private Long revision;
34
+
35
+    /**
36
+     * 主键
37
+     */
38
+    @TableId(type = IdType.AUTO)
39
+    private Long id;
40
+
41
+    /**
42
+     * 查获记录ID
43
+     */
44
+    @Excel(name = "查获记录ID")
45
+    private Long recordId;
46
+
47
+    /**
48
+     * 物品编码
49
+     */
50
+    @Excel(name = "物品编码")
51
+    private String itemCode;
52
+
53
+    /**
54
+     * 数量
55
+     */
56
+    @Excel(name = "数量")
57
+    private BigDecimal quantity;
58
+
59
+    /**
60
+     * 检查部位编码1级
61
+     */
62
+    @Excel(name = "检查部位编码1级")
63
+    private String checkPositionCodeOne;
64
+
65
+    /**
66
+     * 是否故意隐匿(1-是,0-否)
67
+     */
68
+    @Excel(name = "是否故意隐匿(1-是,0-否)")
69
+    private Long isActiveConcealment;
70
+
71
+    /**
72
+     * 检查部位编码2级
73
+     */
74
+    @Excel(name = "检查部位编码2级")
75
+    private String checkPositionCodeTwo;
76
+
77
+    /**
78
+     * 具体位置
79
+     */
80
+    @Excel(name = "具体位置")
81
+    private String checkPositionSpecific;
82
+
83
+    /**
84
+     * 物品名称
85
+     */
86
+    @Excel(name = "物品名称")
87
+    private String itemName;
88
+
89
+    /**
90
+     * 物品分类编码1级
91
+     */
92
+    @Excel(name = "物品分类编码1级")
93
+    private String categoryCodeOne;
94
+
95
+    /**
96
+     * 物品分类名称1级
97
+     */
98
+    @Excel(name = "物品分类名称1级")
99
+    private String categoryNameOne;
100
+
101
+    /**
102
+     * 物品分类编码2级
103
+     */
104
+    @Excel(name = "物品分类编码2级")
105
+    private String categoryCodeTwo;
106
+
107
+    /**
108
+     * 物品分类名称2级
109
+     */
110
+    @Excel(name = "物品分类名称2级")
111
+    private String categoryNameTwo;
112
+
113
+    /**
114
+     * 单位
115
+     */
116
+    @Excel(name = "单位")
117
+    private String unit;
118
+
119
+    /**
120
+     * 检查部位名称1级
121
+     */
122
+    @Excel(name = "检查部位名称1级")
123
+    private String checkPositionNameOne;
124
+
125
+    /**
126
+     * 检查部位名称2级
127
+     */
128
+    @Excel(name = "检查部位名称2级")
129
+    private String checkPositionNameTwo;
130
+
131
+    /**
132
+     * 具体位置
133
+     */
134
+    @Excel(name = "具体位置")
135
+    private String location;
136
+
137
+    /**
138
+     * 具体位置描述
139
+     */
140
+    @Excel(name = "具体位置描述")
141
+    private String locationText;
142
+
143
+    /**
144
+     * 单位名称
145
+     */
146
+    @Excel(name = "单位名称")
147
+    private String unitDesc;
148
+
149
+    /**
150
+     * 处理方式
151
+     */
152
+    @Excel(name = "处理方式")
153
+    private String handlingMethod;
154
+
155
+    /**
156
+     * 处理方式名称
157
+     */
158
+    @Excel(name = "处理方式名称")
159
+    private String handlingMethodDesc;
160
+
161
+    /**
162
+     * 附件ID
163
+     */
164
+    @Excel(name = "附件ID")
165
+    private String attachmentId;
166
+
167
+    /**
168
+     * 附件URL
169
+     */
170
+    @Excel(name = "附件URL")
171
+    private String attachmentUrl;
172
+
173
+    /**
174
+     * 附件名称
175
+     */
176
+    @Excel(name = "附件名称")
177
+    private String attachmentName;
178
+
179
+    /**
180
+     * 附件列表
181
+     */
182
+    private List<BaseAttachment> baseAttachmentList;
183
+
184
+    public void setTenantId(String tenantId) {
185
+        this.tenantId = tenantId;
186
+    }
187
+
188
+    public String getTenantId() {
189
+        return tenantId;
190
+    }
191
+
192
+    public void setRevision(Long revision) {
193
+        this.revision = revision;
194
+    }
195
+
196
+    public Long getRevision() {
197
+        return revision;
198
+    }
199
+
200
+    public void setId(Long id) {
201
+        this.id = id;
202
+    }
203
+
204
+    public Long getId() {
205
+        return id;
206
+    }
207
+
208
+    public void setRecordId(Long recordId) {
209
+        this.recordId = recordId;
210
+    }
211
+
212
+    public Long getRecordId() {
213
+        return recordId;
214
+    }
215
+
216
+    public void setItemCode(String itemCode) {
217
+        this.itemCode = itemCode;
218
+    }
219
+
220
+    public String getItemCode() {
221
+        return itemCode;
222
+    }
223
+
224
+    public void setQuantity(BigDecimal quantity) {
225
+        this.quantity = quantity;
226
+    }
227
+
228
+    public BigDecimal getQuantity() {
229
+        return quantity;
230
+    }
231
+
232
+    public void setCheckPositionCodeOne(String checkPositionCodeOne) {
233
+        this.checkPositionCodeOne = checkPositionCodeOne;
234
+    }
235
+
236
+    public String getCheckPositionCodeOne() {
237
+        return checkPositionCodeOne;
238
+    }
239
+
240
+    public void setIsActiveConcealment(Long isActiveConcealment) {
241
+        this.isActiveConcealment = isActiveConcealment;
242
+    }
243
+
244
+    public Long getIsActiveConcealment() {
245
+        return isActiveConcealment;
246
+    }
247
+
248
+    public void setCheckPositionCodeTwo(String checkPositionCodeTwo) {
249
+        this.checkPositionCodeTwo = checkPositionCodeTwo;
250
+    }
251
+
252
+    public String getCheckPositionCodeTwo() {
253
+        return checkPositionCodeTwo;
254
+    }
255
+
256
+    public void setCheckPositionSpecific(String checkPositionSpecific) {
257
+        this.checkPositionSpecific = checkPositionSpecific;
258
+    }
259
+
260
+    public String getCheckPositionSpecific() {
261
+        return checkPositionSpecific;
262
+    }
263
+
264
+    public void setItemName(String itemName) {
265
+        this.itemName = itemName;
266
+    }
267
+
268
+    public String getItemName() {
269
+        return itemName;
270
+    }
271
+
272
+    public void setCategoryCodeOne(String categoryCodeOne) {
273
+        this.categoryCodeOne = categoryCodeOne;
274
+    }
275
+
276
+    public String getCategoryCodeOne() {
277
+        return categoryCodeOne;
278
+    }
279
+
280
+    public void setCategoryNameOne(String categoryNameOne) {
281
+        this.categoryNameOne = categoryNameOne;
282
+    }
283
+
284
+    public String getCategoryNameOne() {
285
+        return categoryNameOne;
286
+    }
287
+
288
+    public void setCategoryCodeTwo(String categoryCodeTwo) {
289
+        this.categoryCodeTwo = categoryCodeTwo;
290
+    }
291
+
292
+    public String getCategoryCodeTwo() {
293
+        return categoryCodeTwo;
294
+    }
295
+
296
+    public void setCategoryNameTwo(String categoryNameTwo) {
297
+        this.categoryNameTwo = categoryNameTwo;
298
+    }
299
+
300
+    public String getCategoryNameTwo() {
301
+        return categoryNameTwo;
302
+    }
303
+
304
+    public void setUnit(String unit) {
305
+        this.unit = unit;
306
+    }
307
+
308
+    public String getUnit() {
309
+        return unit;
310
+    }
311
+
312
+    public void setCheckPositionNameOne(String checkPositionNameOne) {
313
+        this.checkPositionNameOne = checkPositionNameOne;
314
+    }
315
+
316
+    public String getCheckPositionNameOne() {
317
+        return checkPositionNameOne;
318
+    }
319
+
320
+    public void setCheckPositionNameTwo(String checkPositionNameTwo) {
321
+        this.checkPositionNameTwo = checkPositionNameTwo;
322
+    }
323
+
324
+    public String getCheckPositionNameTwo() {
325
+        return checkPositionNameTwo;
326
+    }
327
+
328
+    public void setUnitDesc(String unitDesc) {
329
+        this.unitDesc = unitDesc;
330
+    }
331
+
332
+    public String getUnitDesc() {
333
+        return unitDesc;
334
+    }
335
+
336
+    public void setHandlingMethod(String handlingMethod) {
337
+        this.handlingMethod = handlingMethod;
338
+    }
339
+
340
+    public String getHandlingMethod() {
341
+        return handlingMethod;
342
+    }
343
+
344
+    public void setHandlingMethodDesc(String handlingMethodDesc) {
345
+        this.handlingMethodDesc = handlingMethodDesc;
346
+    }
347
+
348
+    public String getHandlingMethodDesc() {
349
+        return handlingMethodDesc;
350
+    }
351
+
352
+    public void setAttachmentId(String attachmentId) {
353
+        this.attachmentId = attachmentId;
354
+    }
355
+
356
+    public String getAttachmentId() {
357
+        return attachmentId;
358
+    }
359
+
360
+    public void setAttachmentUrl(String attachmentUrl) {
361
+        this.attachmentUrl = attachmentUrl;
362
+    }
363
+
364
+    public String getAttachmentUrl() {
365
+        return attachmentUrl;
366
+    }
367
+
368
+    public void setAttachmentName(String attachmentName) {
369
+        this.attachmentName = attachmentName;
370
+    }
371
+
372
+    public String getAttachmentName() {
373
+        return attachmentName;
374
+    }
375
+
376
+    public List<BaseAttachment> getBaseAttachmentList() {
377
+        return baseAttachmentList;
378
+    }
379
+
380
+    public void setBaseAttachmentList(List<BaseAttachment> baseAttachmentList) {
381
+        this.baseAttachmentList = baseAttachmentList;
382
+    }
383
+
384
+
385
+    public String getLocation() {
386
+        return location;
387
+    }
388
+
389
+    public void setLocation(String location) {
390
+        this.location = location;
391
+    }
392
+
393
+    public String getLocationText() {
394
+        return locationText;
395
+    }
396
+
397
+    public void setLocationText(String locationText) {
398
+        this.locationText = locationText;
399
+    }
400
+
401
+    @Override
402
+    public String toString() {
403
+        return "ItemSeizureItems{" +
404
+                "tenantId='" + tenantId + '\'' +
405
+                ", revision=" + revision +
406
+                ", id=" + id +
407
+                ", recordId=" + recordId +
408
+                ", itemCode='" + itemCode + '\'' +
409
+                ", quantity=" + quantity +
410
+                ", checkPositionCodeOne='" + checkPositionCodeOne + '\'' +
411
+                ", isActiveConcealment=" + isActiveConcealment +
412
+                ", checkPositionCodeTwo='" + checkPositionCodeTwo + '\'' +
413
+                ", checkPositionSpecific='" + checkPositionSpecific + '\'' +
414
+                ", itemName='" + itemName + '\'' +
415
+                ", categoryCodeOne='" + categoryCodeOne + '\'' +
416
+                ", categoryNameOne='" + categoryNameOne + '\'' +
417
+                ", categoryCodeTwo='" + categoryCodeTwo + '\'' +
418
+                ", categoryNameTwo='" + categoryNameTwo + '\'' +
419
+                ", unit='" + unit + '\'' +
420
+                ", checkPositionNameOne='" + checkPositionNameOne + '\'' +
421
+                ", checkPositionNameTwo='" + checkPositionNameTwo + '\'' +
422
+                ", location='" + location + '\'' +
423
+                ", locationText='" + locationText + '\'' +
424
+                ", unitDesc='" + unitDesc + '\'' +
425
+                ", handlingMethod='" + handlingMethod + '\'' +
426
+                ", handlingMethodDesc='" + handlingMethodDesc + '\'' +
427
+                ", attachmentId='" + attachmentId + '\'' +
428
+                ", attachmentUrl='" + attachmentUrl + '\'' +
429
+                ", attachmentName='" + attachmentName + '\'' +
430
+                ", baseAttachmentList=" + baseAttachmentList +
431
+                '}';
432
+    }
433
+
434
+
435
+}

+ 151 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureParam.java

@@ -0,0 +1,151 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+
4
+import com.fasterxml.jackson.annotation.JsonFormat;
5
+
6
+import java.util.Date;
7
+
8
+/**
9
+ * 查获物品明细对象 item_seizure_items
10
+ *
11
+ * @author ruoyi
12
+ * @date 2025-07-10
13
+ */
14
+public class ItemSeizureParam {
15
+    private static final long serialVersionUID = 1L;
16
+
17
+    /**
18
+     * 查获记录类型:1=我的查获记录;2=本班组查获记录
19
+     */
20
+    private int recordType = 1;
21
+
22
+    /**
23
+     * 查获记录类型:1=我的查获记录:检查人员ID
24
+     */
25
+    private Long inspectUserId;
26
+
27
+    /**
28
+     * 查获记录类型:2=本班组查获记录:查获人机构站ID
29
+     */
30
+    private Long inspectStationId;
31
+
32
+    /**
33
+     * 查获记录类型:2=本班组查获记录:查获人科室ID
34
+     */
35
+    private Long inspectDepartmentId;
36
+
37
+    /**
38
+     * 查获记录类型:2=本班组查获记录:查获人班组ID
39
+     */
40
+    private Long inspectTeamId;
41
+
42
+    /**
43
+     * 时间范围:1=今日;2=本周;3=本月;4=自定义
44
+     */
45
+    private int timeType = 1;
46
+
47
+    /**
48
+     * 时间范围:4=自定义:开始日期
49
+     */
50
+    @JsonFormat(pattern = "yyyy-MM-dd")
51
+    private Date startDate;
52
+
53
+    /**
54
+     * 时间范围:4=自定义:结束日期
55
+     */
56
+    @JsonFormat(pattern = "yyyy-MM-dd")
57
+    private Date endDate;
58
+
59
+    /**
60
+     * 分类类型:ALL=全部;其他=对应类型
61
+     */
62
+    private String seizureType = "ALL";
63
+
64
+    public int getRecordType() {
65
+        return recordType;
66
+    }
67
+
68
+    public void setRecordType(int recordType) {
69
+        this.recordType = recordType;
70
+    }
71
+
72
+    public Long getInspectUserId() {
73
+        return inspectUserId;
74
+    }
75
+
76
+    public void setInspectUserId(Long inspectUserId) {
77
+        this.inspectUserId = inspectUserId;
78
+    }
79
+
80
+    public Long getInspectStationId() {
81
+        return inspectStationId;
82
+    }
83
+
84
+    public void setInspectStationId(Long inspectStationId) {
85
+        this.inspectStationId = inspectStationId;
86
+    }
87
+
88
+    public Long getInspectDepartmentId() {
89
+        return inspectDepartmentId;
90
+    }
91
+
92
+    public void setInspectDepartmentId(Long inspectDepartmentId) {
93
+        this.inspectDepartmentId = inspectDepartmentId;
94
+    }
95
+
96
+    public Long getInspectTeamId() {
97
+        return inspectTeamId;
98
+    }
99
+
100
+    public void setInspectTeamId(Long inspectTeamId) {
101
+        this.inspectTeamId = inspectTeamId;
102
+    }
103
+
104
+    public int getTimeType() {
105
+        return timeType;
106
+    }
107
+
108
+    public void setTimeType(int timeType) {
109
+        this.timeType = timeType;
110
+    }
111
+
112
+    public Date getStartDate() {
113
+        return startDate;
114
+    }
115
+
116
+    public void setStartDate(Date startDate) {
117
+        this.startDate = startDate;
118
+    }
119
+
120
+    public Date getEndDate() {
121
+        return endDate;
122
+    }
123
+
124
+    public void setEndDate(Date endDate) {
125
+        this.endDate = endDate;
126
+    }
127
+
128
+    public String getSeizureType() {
129
+        return seizureType;
130
+    }
131
+
132
+    public void setSeizureType(String seizureType) {
133
+        this.seizureType = seizureType;
134
+    }
135
+
136
+    @Override
137
+    public String toString() {
138
+        return "ItemSeizureParam{" +
139
+                "recordType=" + recordType +
140
+                ", inspectUserId=" + inspectUserId +
141
+                ", inspectStationId=" + inspectStationId +
142
+                ", inspectDepartmentId=" + inspectDepartmentId +
143
+                ", inspectTeamId=" + inspectTeamId +
144
+                ", timeType=" + timeType +
145
+                ", startDate=" + startDate +
146
+                ", endDate=" + endDate +
147
+                ", seizureType='" + seizureType + '\'' +
148
+                '}';
149
+    }
150
+
151
+}

+ 538 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureRecord.java

@@ -0,0 +1,538 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import java.util.Date;
4
+import java.util.List;
5
+
6
+import com.baomidou.mybatisplus.annotation.IdType;
7
+import com.baomidou.mybatisplus.annotation.TableId;
8
+import com.baomidou.mybatisplus.annotation.TableName;
9
+import com.fasterxml.jackson.annotation.JsonFormat;
10
+import org.apache.commons.lang3.builder.ToStringBuilder;
11
+import org.apache.commons.lang3.builder.ToStringStyle;
12
+import com.sundot.airport.common.annotation.Excel;
13
+import com.sundot.airport.common.core.domain.BaseEntity;
14
+
15
+/**
16
+ * 查获记录对象 item_seizure_record
17
+ *
18
+ * @author ruoyi
19
+ * @date 2025-07-10
20
+ */
21
+@TableName("item_seizure_record")
22
+public class ItemSeizureRecord extends BaseEntity {
23
+    private static final long serialVersionUID = 1L;
24
+
25
+    /**
26
+     * 租户号
27
+     */
28
+    private String tenantId;
29
+
30
+    /**
31
+     * 乐观锁
32
+     */
33
+    private Integer revision;
34
+
35
+    /**
36
+     * 检查人员ID
37
+     */
38
+    @Excel(name = "检查人员ID")
39
+    private Long inspectUserId;
40
+
41
+    /**
42
+     * 通道编码
43
+     */
44
+    @Excel(name = "通道编码")
45
+    private String channelCode;
46
+
47
+    /**
48
+     * 查获时间
49
+     */
50
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
51
+    @Excel(name = "查获时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
52
+    private Date seizureTime;
53
+
54
+    /**
55
+     * 检查岗位
56
+     */
57
+    @Excel(name = "检查岗位")
58
+    private String checkMethod;
59
+
60
+    /**
61
+     * 考勤记录ID
62
+     */
63
+    @Excel(name = "考勤记录ID")
64
+    private Long attendanceId;
65
+
66
+    /**
67
+     * 主键
68
+     */
69
+    @TableId(type = IdType.AUTO)
70
+    private Long id;
71
+
72
+    /**
73
+     * 考勤班组ID
74
+     */
75
+    @Excel(name = "考勤班组ID")
76
+    private Long attendanceTeamId;
77
+
78
+    /**
79
+     * 考勤班组名称
80
+     */
81
+    @Excel(name = "考勤班组名称")
82
+    private String attendanceTeamName;
83
+
84
+    /**
85
+     * 考勤科室ID
86
+     */
87
+    @Excel(name = "考勤科室ID")
88
+    private Long attendanceDepartmentId;
89
+
90
+    /**
91
+     * 考勤科室名称
92
+     */
93
+    @Excel(name = "考勤科室名称")
94
+    private String attendanceDepartmentName;
95
+
96
+    /**
97
+     * 考勤机构站ID
98
+     */
99
+    @Excel(name = "考勤机构站ID")
100
+    private Long attendanceStationId;
101
+
102
+    /**
103
+     * 考勤机构站名称
104
+     */
105
+    @Excel(name = "考勤机构站名称")
106
+    private String attendanceStationName;
107
+
108
+    /**
109
+     * 通道名称
110
+     */
111
+    @Excel(name = "通道名称")
112
+    private String channelName;
113
+
114
+    /**
115
+     * 区域编码
116
+     */
117
+    @Excel(name = "区域编码")
118
+    private Long regionalCode;
119
+
120
+    /**
121
+     * 区域名称
122
+     */
123
+    @Excel(name = "区域名称")
124
+    private String regionalName;
125
+
126
+    /**
127
+     * 航站楼编码
128
+     */
129
+    @Excel(name = "航站楼编码")
130
+    private Long terminlCode;
131
+
132
+    /**
133
+     * 航站楼名称
134
+     */
135
+    @Excel(name = "航站楼名称")
136
+    private String terminlName;
137
+
138
+    /**
139
+     * 旅客姓名
140
+     */
141
+    @Excel(name = "旅客姓名")
142
+    private String passengerName;
143
+
144
+    /**
145
+     * 旅客性别
146
+     */
147
+    @Excel(name = "旅客性别")
148
+    private String passengerGender;
149
+
150
+    /**
151
+     * 旅客身份证号
152
+     */
153
+    @Excel(name = "旅客身份证号")
154
+    private String passengerCard;
155
+
156
+    /**
157
+     * 航班号
158
+     */
159
+    @Excel(name = "航班号")
160
+    private String passengerFlight;
161
+
162
+    /**
163
+     * 查获人班组ID
164
+     */
165
+    @Excel(name = "查获人班组ID")
166
+    private Long inspectTeamId;
167
+
168
+    /**
169
+     * 查获人班组名称
170
+     */
171
+    @Excel(name = "查获人班组名称")
172
+    private String inspectTeamName;
173
+
174
+    /**
175
+     * 查获人科室ID
176
+     */
177
+    @Excel(name = "查获人科室ID")
178
+    private Long inspectDepartmentId;
179
+
180
+    /**
181
+     * 查获人科室名称
182
+     */
183
+    @Excel(name = "查获人科室名称")
184
+    private String inspectDepartmentName;
185
+
186
+    /**
187
+     * 查获人机构站ID
188
+     */
189
+    @Excel(name = "查获人机构站ID")
190
+    private Long inspectStationId;
191
+
192
+    /**
193
+     * 查获人机构站名称
194
+     */
195
+    @Excel(name = "查获人机构站名称")
196
+    private String inspectStationName;
197
+
198
+    /**
199
+     * 检查岗位名称
200
+     */
201
+    @Excel(name = "检查岗位名称")
202
+    private String checkMethodDesc;
203
+
204
+    /**
205
+     * 旅客性别名称
206
+     */
207
+    @Excel(name = "旅客性别名称")
208
+    private String passengerGenderDesc;
209
+
210
+    /**
211
+     * 检查人员名称
212
+     */
213
+    @Excel(name = "检查人员名称")
214
+    private String inspectUserName;
215
+
216
+    /**
217
+     * 流程状态 0草稿,1审核中,2 人工终止 ,3归档
218
+     */
219
+    @Excel(name = "流程状态 0草稿,1审核中,2 人工终止 ,3归档")
220
+    private String processStatus;
221
+
222
+    /**
223
+     * 查获物品明细列表
224
+     */
225
+    private List<ItemSeizureItems> itemSeizureItemsList;
226
+
227
+    public String getProcessStatus() {
228
+        return processStatus;
229
+    }
230
+
231
+    public void setProcessStatus(String processStatus) {
232
+        this.processStatus = processStatus;
233
+    }
234
+
235
+    public void setTenantId(String tenantId) {
236
+        this.tenantId = tenantId;
237
+    }
238
+
239
+    public String getTenantId() {
240
+        return tenantId;
241
+    }
242
+
243
+    public void setRevision(Integer revision) {
244
+        this.revision = revision;
245
+    }
246
+
247
+    public Integer getRevision() {
248
+        return revision;
249
+    }
250
+
251
+    public void setInspectUserId(Long inspectUserId) {
252
+        this.inspectUserId = inspectUserId;
253
+    }
254
+
255
+    public Long getInspectUserId() {
256
+        return inspectUserId;
257
+    }
258
+
259
+    public void setChannelCode(String channelCode) {
260
+        this.channelCode = channelCode;
261
+    }
262
+
263
+    public String getChannelCode() {
264
+        return channelCode;
265
+    }
266
+
267
+    public void setSeizureTime(Date seizureTime) {
268
+        this.seizureTime = seizureTime;
269
+    }
270
+
271
+    public Date getSeizureTime() {
272
+        return seizureTime;
273
+    }
274
+
275
+    public void setCheckMethod(String checkMethod) {
276
+        this.checkMethod = checkMethod;
277
+    }
278
+
279
+    public String getCheckMethod() {
280
+        return checkMethod;
281
+    }
282
+
283
+    public void setAttendanceId(Long attendanceId) {
284
+        this.attendanceId = attendanceId;
285
+    }
286
+
287
+    public Long getAttendanceId() {
288
+        return attendanceId;
289
+    }
290
+
291
+    public void setId(Long id) {
292
+        this.id = id;
293
+    }
294
+
295
+    public Long getId() {
296
+        return id;
297
+    }
298
+
299
+    public void setAttendanceTeamId(Long attendanceTeamId) {
300
+        this.attendanceTeamId = attendanceTeamId;
301
+    }
302
+
303
+    public Long getAttendanceTeamId() {
304
+        return attendanceTeamId;
305
+    }
306
+
307
+    public void setAttendanceTeamName(String attendanceTeamName) {
308
+        this.attendanceTeamName = attendanceTeamName;
309
+    }
310
+
311
+    public String getAttendanceTeamName() {
312
+        return attendanceTeamName;
313
+    }
314
+
315
+    public void setAttendanceDepartmentId(Long attendanceDepartmentId) {
316
+        this.attendanceDepartmentId = attendanceDepartmentId;
317
+    }
318
+
319
+    public Long getAttendanceDepartmentId() {
320
+        return attendanceDepartmentId;
321
+    }
322
+
323
+    public void setAttendanceDepartmentName(String attendanceDepartmentName) {
324
+        this.attendanceDepartmentName = attendanceDepartmentName;
325
+    }
326
+
327
+    public String getAttendanceDepartmentName() {
328
+        return attendanceDepartmentName;
329
+    }
330
+
331
+    public void setAttendanceStationId(Long attendanceStationId) {
332
+        this.attendanceStationId = attendanceStationId;
333
+    }
334
+
335
+    public Long getAttendanceStationId() {
336
+        return attendanceStationId;
337
+    }
338
+
339
+    public void setAttendanceStationName(String attendanceStationName) {
340
+        this.attendanceStationName = attendanceStationName;
341
+    }
342
+
343
+    public String getAttendanceStationName() {
344
+        return attendanceStationName;
345
+    }
346
+
347
+    public void setChannelName(String channelName) {
348
+        this.channelName = channelName;
349
+    }
350
+
351
+    public String getChannelName() {
352
+        return channelName;
353
+    }
354
+
355
+    public void setRegionalCode(Long regionalCode) {
356
+        this.regionalCode = regionalCode;
357
+    }
358
+
359
+    public Long getRegionalCode() {
360
+        return regionalCode;
361
+    }
362
+
363
+    public void setRegionalName(String regionalName) {
364
+        this.regionalName = regionalName;
365
+    }
366
+
367
+    public String getRegionalName() {
368
+        return regionalName;
369
+    }
370
+
371
+    public void setTerminlCode(Long terminlCode) {
372
+        this.terminlCode = terminlCode;
373
+    }
374
+
375
+    public Long getTerminlCode() {
376
+        return terminlCode;
377
+    }
378
+
379
+    public void setTerminlName(String terminlName) {
380
+        this.terminlName = terminlName;
381
+    }
382
+
383
+    public String getTerminlName() {
384
+        return terminlName;
385
+    }
386
+
387
+    public void setPassengerName(String passengerName) {
388
+        this.passengerName = passengerName;
389
+    }
390
+
391
+    public String getPassengerName() {
392
+        return passengerName;
393
+    }
394
+
395
+    public void setPassengerGender(String passengerGender) {
396
+        this.passengerGender = passengerGender;
397
+    }
398
+
399
+    public String getPassengerGender() {
400
+        return passengerGender;
401
+    }
402
+
403
+    public void setPassengerCard(String passengerCard) {
404
+        this.passengerCard = passengerCard;
405
+    }
406
+
407
+    public String getPassengerCard() {
408
+        return passengerCard;
409
+    }
410
+
411
+    public void setPassengerFlight(String passengerFlight) {
412
+        this.passengerFlight = passengerFlight;
413
+    }
414
+
415
+    public String getPassengerFlight() {
416
+        return passengerFlight;
417
+    }
418
+
419
+    public void setInspectTeamId(Long inspectTeamId) {
420
+        this.inspectTeamId = inspectTeamId;
421
+    }
422
+
423
+    public Long getInspectTeamId() {
424
+        return inspectTeamId;
425
+    }
426
+
427
+    public void setInspectTeamName(String inspectTeamName) {
428
+        this.inspectTeamName = inspectTeamName;
429
+    }
430
+
431
+    public String getInspectTeamName() {
432
+        return inspectTeamName;
433
+    }
434
+
435
+    public void setInspectDepartmentId(Long inspectDepartmentId) {
436
+        this.inspectDepartmentId = inspectDepartmentId;
437
+    }
438
+
439
+    public Long getInspectDepartmentId() {
440
+        return inspectDepartmentId;
441
+    }
442
+
443
+    public void setInspectDepartmentName(String inspectDepartmentName) {
444
+        this.inspectDepartmentName = inspectDepartmentName;
445
+    }
446
+
447
+    public String getInspectDepartmentName() {
448
+        return inspectDepartmentName;
449
+    }
450
+
451
+    public void setInspectStationId(Long inspectStationId) {
452
+        this.inspectStationId = inspectStationId;
453
+    }
454
+
455
+    public Long getInspectStationId() {
456
+        return inspectStationId;
457
+    }
458
+
459
+    public void setInspectStationName(String inspectStationName) {
460
+        this.inspectStationName = inspectStationName;
461
+    }
462
+
463
+    public String getInspectStationName() {
464
+        return inspectStationName;
465
+    }
466
+
467
+    public void setCheckMethodDesc(String checkMethodDesc) {
468
+        this.checkMethodDesc = checkMethodDesc;
469
+    }
470
+
471
+    public String getCheckMethodDesc() {
472
+        return checkMethodDesc;
473
+    }
474
+
475
+    public void setPassengerGenderDesc(String passengerGenderDesc) {
476
+        this.passengerGenderDesc = passengerGenderDesc;
477
+    }
478
+
479
+    public String getPassengerGenderDesc() {
480
+        return passengerGenderDesc;
481
+    }
482
+
483
+    public void setInspectUserName(String inspectUserName) {
484
+        this.inspectUserName = inspectUserName;
485
+    }
486
+
487
+    public String getInspectUserName() {
488
+        return inspectUserName;
489
+    }
490
+
491
+    public List<ItemSeizureItems> getItemSeizureItemsList() {
492
+        return itemSeizureItemsList;
493
+    }
494
+
495
+    public void setItemSeizureItemsList(List<ItemSeizureItems> itemSeizureItemsList) {
496
+        this.itemSeizureItemsList = itemSeizureItemsList;
497
+    }
498
+
499
+    @Override
500
+    public String toString() {
501
+        return "ItemSeizureRecord{" +
502
+                "tenantId='" + tenantId + '\'' +
503
+                ", revision=" + revision +
504
+                ", inspectUserId=" + inspectUserId +
505
+                ", channelCode='" + channelCode + '\'' +
506
+                ", seizureTime=" + seizureTime +
507
+                ", checkMethod='" + checkMethod + '\'' +
508
+                ", attendanceId=" + attendanceId +
509
+                ", id=" + id +
510
+                ", attendanceTeamId=" + attendanceTeamId +
511
+                ", attendanceTeamName='" + attendanceTeamName + '\'' +
512
+                ", attendanceDepartmentId=" + attendanceDepartmentId +
513
+                ", attendanceDepartmentName='" + attendanceDepartmentName + '\'' +
514
+                ", attendanceStationId=" + attendanceStationId +
515
+                ", attendanceStationName='" + attendanceStationName + '\'' +
516
+                ", channelName='" + channelName + '\'' +
517
+                ", regionalCode=" + regionalCode +
518
+                ", regionalName='" + regionalName + '\'' +
519
+                ", terminlCode=" + terminlCode +
520
+                ", terminlName='" + terminlName + '\'' +
521
+                ", passengerName='" + passengerName + '\'' +
522
+                ", passengerGender='" + passengerGender + '\'' +
523
+                ", passengerCard='" + passengerCard + '\'' +
524
+                ", passengerFlight='" + passengerFlight + '\'' +
525
+                ", inspectTeamId=" + inspectTeamId +
526
+                ", inspectTeamName='" + inspectTeamName + '\'' +
527
+                ", inspectDepartmentId=" + inspectDepartmentId +
528
+                ", inspectDepartmentName='" + inspectDepartmentName + '\'' +
529
+                ", inspectStationId=" + inspectStationId +
530
+                ", inspectStationName='" + inspectStationName + '\'' +
531
+                ", checkMethodDesc='" + checkMethodDesc + '\'' +
532
+                ", passengerGenderDesc='" + passengerGenderDesc + '\'' +
533
+                ", inspectUserName='" + inspectUserName + '\'' +
534
+                ", processStatus='" + processStatus + '\'' +
535
+                ", itemSeizureItemsList=" + itemSeizureItemsList +
536
+                '}';
537
+    }
538
+}

+ 24 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureRecordDTO.java

@@ -0,0 +1,24 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+
4
+import com.fasterxml.jackson.annotation.JsonFormat;
5
+import lombok.Data;
6
+import lombok.EqualsAndHashCode;
7
+
8
+import java.util.Date;
9
+
10
+@EqualsAndHashCode(callSuper = true)
11
+@Data
12
+public class ItemSeizureRecordDTO extends ItemSeizureRecord{
13
+    /**
14
+     * 开始时间
15
+     */
16
+    @JsonFormat(pattern = "yyyy-MM-dd")
17
+    private Date beginTime;
18
+    /**
19
+     * 结束时间
20
+     */
21
+    @JsonFormat(pattern = "yyyy-MM-dd")
22
+    private Date endTime;
23
+
24
+}

+ 59 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemSeizureTotal.java

@@ -0,0 +1,59 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import java.math.BigDecimal;
4
+
5
+/**
6
+ * 查获物品分类数量
7
+ */
8
+public class ItemSeizureTotal {
9
+
10
+    private static final long serialVersionUID = 1L;
11
+
12
+    /**
13
+     * 总数量
14
+     */
15
+    private BigDecimal total;
16
+    /**
17
+     * 移交公安数量
18
+     */
19
+    private BigDecimal policeTotal;
20
+
21
+    /**
22
+     * 故意隐匿数量
23
+     */
24
+    private BigDecimal concealTotal;
25
+
26
+    public BigDecimal getTotal() {
27
+        return total;
28
+    }
29
+
30
+    public void setTotal(BigDecimal total) {
31
+        this.total = total;
32
+    }
33
+
34
+    public BigDecimal getPoliceTotal() {
35
+        return policeTotal;
36
+    }
37
+
38
+    public void setPoliceTotal(BigDecimal policeTotal) {
39
+        this.policeTotal = policeTotal;
40
+    }
41
+
42
+    public BigDecimal getConcealTotal() {
43
+        return concealTotal;
44
+    }
45
+
46
+    public void setConcealTotal(BigDecimal concealTotal) {
47
+        this.concealTotal = concealTotal;
48
+    }
49
+
50
+    @Override
51
+    public String toString() {
52
+        return "ItemSeizureTotal{" +
53
+                "total=" + total +
54
+                ", policeTotal=" + policeTotal +
55
+                ", concealTotal=" + concealTotal +
56
+                '}';
57
+    }
58
+
59
+}

+ 29 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/portrait/ItemSeizureModuleIndicatorResult.java

@@ -0,0 +1,29 @@
1
+package com.sundot.airport.item.domain.portrait;
2
+
3
+import com.sundot.airport.common.domain.portrait.BaseModuleIndicatorResult;
4
+import io.swagger.annotations.ApiModelProperty;
5
+import lombok.Data;
6
+
7
+/**
8
+ * 查获物模块指标结果类
9
+ * 用于存储查获物模块的指标数据
10
+ */
11
+@Data
12
+public class ItemSeizureModuleIndicatorResult extends BaseModuleIndicatorResult {
13
+    
14
+    /** 有效查获数量 */
15
+    @ApiModelProperty("有效查获数量")
16
+    private Object effectiveSeizureCount;
17
+    
18
+    /** 故意隐匿查获数量 */
19
+    @ApiModelProperty("故意隐匿查获数量")
20
+    private Object willfulConcealmentCount;
21
+    
22
+    /** 移交公安查获数量 */
23
+    @ApiModelProperty("移交公安查获数量")
24
+    private Object referToPoliceCount;
25
+    
26
+    public ItemSeizureModuleIndicatorResult() {
27
+        setModuleName("item");
28
+    }
29
+}

+ 16 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/portrait/SeizureStats.java

@@ -0,0 +1,16 @@
1
+package com.sundot.airport.item.domain.portrait;
2
+
3
+import lombok.Data;
4
+
5
+/**
6
+ * 查获物统计信息
7
+ * 用于表示个人或组织的查获物统计信息
8
+ */
9
+@Data
10
+public class SeizureStats {
11
+    /** 总数量 */
12
+    private Long totalCount;
13
+    
14
+    /** 个人统计时为数量,组织统计时为总量 */
15
+    private Long count;
16
+}

+ 83 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/vo/ItemSeizureRecordExportVO.java

@@ -0,0 +1,83 @@
1
+package com.sundot.airport.item.domain.vo;
2
+
3
+import com.sundot.airport.common.annotation.Excel;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+import java.util.Date;
8
+
9
+/**
10
+ * 查获记录导出VO对象
11
+ *
12
+ */
13
+@Data
14
+public class ItemSeizureRecordExportVO {
15
+
16
+    /**
17
+     * 安检员
18
+     */
19
+    @Excel(name = "安检员", sort = 1)
20
+    private String inspectUserName;
21
+
22
+    /**
23
+     * 查获时间
24
+     */
25
+    @Excel(name = "查获时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", sort = 2)
26
+    private Date seizureTime;
27
+
28
+    /**
29
+     * 安检位置
30
+     */
31
+    @Excel(name = "安检位置", sort = 3)
32
+    private String channelName;
33
+
34
+    /**
35
+     * 安检岗位
36
+     */
37
+    @Excel(name = "安检岗位", sort = 4)
38
+    private String checkMethodDesc;
39
+
40
+    /**
41
+     * 查获班组
42
+     */
43
+    @Excel(name = "查获班组", sort = 5)
44
+    private String inspectTeamName;
45
+
46
+    /**
47
+     * 上报班组
48
+     */
49
+    @Excel(name = "上报班组", sort = 6)
50
+    private String attendanceTeamName;
51
+
52
+    /**
53
+     * 违禁品类别/类型
54
+     */
55
+    @Excel(name = "违禁品类别/类型", sort = 7)
56
+    private String categoryNameTwo;
57
+
58
+    /**
59
+     * 数量
60
+     */
61
+    @Excel(name = "数量", sort = 8)
62
+    private BigDecimal quantity;
63
+
64
+    /**
65
+     * 部位类别/类型
66
+     */
67
+    @Excel(name = "部位类别/类型", sort = 9)
68
+    private String checkPositionNameTwo;
69
+
70
+    /**
71
+     * 处理方式
72
+     */
73
+    @Excel(name = "处理方式", sort = 10)
74
+    private String handlingMethod;
75
+
76
+    /**
77
+     * 是否隐匿夹带
78
+     */
79
+    @Excel(name = "是否隐匿夹带", sort = 11)
80
+    private String isActiveConcealmentDesc;
81
+
82
+
83
+}

+ 0 - 0
airport-item/src/main/java/com/sundot/airport/item/mapper/ItemLargeScreenMapper.java


Některé soubory nejsou zobrazny, neboť je v této revizi změněno mnoho souborů