Bläddra i källkod

配分事项录入排序

chenshudong 1 vecka sedan
förälder
incheckning
27c46788e9

+ 47 - 6
airport-admin/src/main/java/com/sundot/airport/web/controller/score/ScoreEventController.java

@@ -11,6 +11,7 @@ import com.sundot.airport.common.core.page.TableDataInfo;
11
 import com.sundot.airport.common.enums.BusinessType;
11
 import com.sundot.airport.common.enums.BusinessType;
12
 import com.sundot.airport.common.enums.ScoreTypeEnum;
12
 import com.sundot.airport.common.enums.ScoreTypeEnum;
13
 import com.sundot.airport.common.utils.DateUtils;
13
 import com.sundot.airport.common.utils.DateUtils;
14
+import com.sundot.airport.common.utils.NameUtils;
14
 import com.sundot.airport.common.utils.poi.ExcelUtil;
15
 import com.sundot.airport.common.utils.poi.ExcelUtil;
15
 import com.sundot.airport.ledger.domain.ScoreEvent;
16
 import com.sundot.airport.ledger.domain.ScoreEvent;
16
 import com.sundot.airport.ledger.domain.ScoreIndicator;
17
 import com.sundot.airport.ledger.domain.ScoreIndicator;
@@ -28,7 +29,12 @@ import org.springframework.web.multipart.MultipartFile;
28
 import javax.servlet.http.HttpServletResponse;
29
 import javax.servlet.http.HttpServletResponse;
29
 import java.math.BigDecimal;
30
 import java.math.BigDecimal;
30
 import java.util.ArrayList;
31
 import java.util.ArrayList;
32
+import java.util.Collections;
33
+import java.util.HashSet;
34
+import java.util.LinkedHashMap;
31
 import java.util.List;
35
 import java.util.List;
36
+import java.util.Map;
37
+import java.util.Set;
32
 import java.util.UUID;
38
 import java.util.UUID;
33
 
39
 
34
 /**
40
 /**
@@ -38,6 +44,16 @@ import java.util.UUID;
38
 @RequestMapping("/score/event")
44
 @RequestMapping("/score/event")
39
 public class ScoreEventController extends BaseController {
45
 public class ScoreEventController extends BaseController {
40
 
46
 
47
+    // 排序字段白名单(防 SQL 注入)
48
+    private static final Set<String> ALLOWED_SORT_COLUMNS;
49
+
50
+    static {
51
+        Set<String> set = new HashSet<>();
52
+        set.add("create_time");
53
+        set.add("event_time");
54
+        ALLOWED_SORT_COLUMNS = Collections.unmodifiableSet(set);
55
+    }
56
+
41
     @Autowired
57
     @Autowired
42
     private IScoreEventService service;
58
     private IScoreEventService service;
43
 
59
 
@@ -51,6 +67,9 @@ public class ScoreEventController extends BaseController {
51
     @GetMapping("/list")
67
     @GetMapping("/list")
52
     public TableDataInfo list(ScoreEvent query) {
68
     public TableDataInfo list(ScoreEvent query) {
53
         startPage();
69
         startPage();
70
+        // 排序字段白名单过滤
71
+        Map<String, String> safeSort = buildSafeSort(query.getSorts());
72
+        query.setSorts(safeSort);
54
         return getDataTable(service.selectList(query));
73
         return getDataTable(service.selectList(query));
55
     }
74
     }
56
 
75
 
@@ -75,10 +94,10 @@ public class ScoreEventController extends BaseController {
75
         entity.setSourceType("1");
94
         entity.setSourceType("1");
76
         entity.setCreateBy(getUsername());
95
         entity.setCreateBy(getUsername());
77
         entity.setCreateTime(DateUtils.getNowDate());
96
         entity.setCreateTime(DateUtils.getNowDate());
78
-        
97
+
79
         // 通过指标名称查找并设置ID
98
         // 通过指标名称查找并设置ID
80
         resolveIndicatorIds(entity);
99
         resolveIndicatorIds(entity);
81
-        
100
+
82
         // 计算 totalScore
101
         // 计算 totalScore
83
         BigDecimal score = entity.getScoreValue() != null ? entity.getScoreValue() : BigDecimal.ZERO;
102
         BigDecimal score = entity.getScoreValue() != null ? entity.getScoreValue() : BigDecimal.ZERO;
84
         BigDecimal cascade = entity.getCascadeScore() != null ? entity.getCascadeScore() : BigDecimal.ZERO;
103
         BigDecimal cascade = entity.getCascadeScore() != null ? entity.getCascadeScore() : BigDecimal.ZERO;
@@ -99,10 +118,10 @@ public class ScoreEventController extends BaseController {
99
     public AjaxResult edit(@Validated @RequestBody ScoreEvent entity) {
118
     public AjaxResult edit(@Validated @RequestBody ScoreEvent entity) {
100
         entity.setUpdateBy(getUsername());
119
         entity.setUpdateBy(getUsername());
101
         entity.setUpdateTime(DateUtils.getNowDate());
120
         entity.setUpdateTime(DateUtils.getNowDate());
102
-        
121
+
103
         // 通过指标名称查找并设置ID
122
         // 通过指标名称查找并设置ID
104
         resolveIndicatorIds(entity);
123
         resolveIndicatorIds(entity);
105
-        
124
+
106
         BigDecimal score = entity.getScoreValue() != null ? entity.getScoreValue() : BigDecimal.ZERO;
125
         BigDecimal score = entity.getScoreValue() != null ? entity.getScoreValue() : BigDecimal.ZERO;
107
         BigDecimal cascade = entity.getCascadeScore() != null ? entity.getCascadeScore() : BigDecimal.ZERO;
126
         BigDecimal cascade = entity.getCascadeScore() != null ? entity.getCascadeScore() : BigDecimal.ZERO;
108
         entity.setTotalScore(score.add(cascade));
127
         entity.setTotalScore(score.add(cascade));
@@ -156,7 +175,7 @@ public class ScoreEventController extends BaseController {
156
                 entity.setLevel2Id(level2Id);
175
                 entity.setLevel2Id(level2Id);
157
             }
176
             }
158
         }
177
         }
159
-        
178
+
160
         // 通过三级指标名称查找ID
179
         // 通过三级指标名称查找ID
161
         if (entity.getLevel3Name() != null && !entity.getLevel3Name().trim().isEmpty() && entity.getLevel3Id() == null) {
180
         if (entity.getLevel3Name() != null && !entity.getLevel3Name().trim().isEmpty() && entity.getLevel3Id() == null) {
162
             Long level3Id = findIndicatorIdByName(entity.getLevel3Name().trim());
181
             Long level3Id = findIndicatorIdByName(entity.getLevel3Name().trim());
@@ -164,7 +183,7 @@ public class ScoreEventController extends BaseController {
164
                 entity.setLevel3Id(level3Id);
183
                 entity.setLevel3Id(level3Id);
165
             }
184
             }
166
         }
185
         }
167
-        
186
+
168
         // 通过四级指标名称查找ID
187
         // 通过四级指标名称查找ID
169
         if (entity.getLevel4Name() != null && !entity.getLevel4Name().trim().isEmpty() && entity.getLevel4Id() == null) {
188
         if (entity.getLevel4Name() != null && !entity.getLevel4Name().trim().isEmpty() && entity.getLevel4Id() == null) {
170
             Long level4Id = findIndicatorIdByName(entity.getLevel4Name().trim());
189
             Long level4Id = findIndicatorIdByName(entity.getLevel4Name().trim());
@@ -210,4 +229,26 @@ public class ScoreEventController extends BaseController {
210
         }
229
         }
211
         return basePositionService.selectBasePositionById(regional.getParentId());
230
         return basePositionService.selectBasePositionById(regional.getParentId());
212
     }
231
     }
232
+
233
+    /**
234
+     * 构建安全的排序参数
235
+     */
236
+    private Map<String, String> buildSafeSort(Map<String, String> sorts) {
237
+        Map<String, String> result = new LinkedHashMap<>();
238
+
239
+        if (sorts == null) {
240
+            return result;
241
+        }
242
+
243
+        for (Map.Entry<String, String> entry : sorts.entrySet()) {
244
+            String field = NameUtils.camelToUnderscore(entry.getKey());
245
+            if (!ALLOWED_SORT_COLUMNS.contains(field)) {
246
+                continue;
247
+            }
248
+            String direction = "desc".equalsIgnoreCase(String.valueOf(entry.getValue())) ? "desc" : "asc";
249
+
250
+            result.put(field, direction);
251
+        }
252
+        return result;
253
+    }
213
 }
254
 }

+ 15 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/BaseEntity.java

@@ -59,6 +59,13 @@ public class BaseEntity implements Serializable {
59
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
59
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
60
     private Map<String, Object> params;
60
     private Map<String, Object> params;
61
 
61
 
62
+    /**
63
+     * 排序参数
64
+     */
65
+    @TableField(exist = false)
66
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
67
+    private Map<String, String> sorts;
68
+
62
     public String getSearchValue() {
69
     public String getSearchValue() {
63
         return searchValue;
70
         return searchValue;
64
     }
71
     }
@@ -117,4 +124,12 @@ public class BaseEntity implements Serializable {
117
     public void setParams(Map<String, Object> params) {
124
     public void setParams(Map<String, Object> params) {
118
         this.params = params;
125
         this.params = params;
119
     }
126
     }
127
+
128
+    public Map<String, String> getSorts() {
129
+        return sorts;
130
+    }
131
+
132
+    public void setSorts(Map<String, String> sorts) {
133
+        this.sorts = sorts;
134
+    }
120
 }
135
 }

+ 28 - 0
airport-common/src/main/java/com/sundot/airport/common/utils/NameUtils.java

@@ -0,0 +1,28 @@
1
+package com.sundot.airport.common.utils;
2
+
3
+/**
4
+ * 字段名称工具类
5
+ */
6
+public class NameUtils {
7
+
8
+    /**
9
+     * 驼峰转下划线
10
+     * @param name
11
+     * @return
12
+     */
13
+    public static String camelToUnderscore(String name) {
14
+        if (name == null || name.isEmpty()) {
15
+            return name;
16
+        }
17
+        StringBuilder sb = new StringBuilder();
18
+        for (char c : name.toCharArray()) {
19
+            if (Character.isUpperCase(c)) {
20
+                sb.append("_").append(Character.toLowerCase(c));
21
+            } else {
22
+                sb.append(c);
23
+            }
24
+        }
25
+        return sb.toString();
26
+    }
27
+
28
+}

+ 18 - 1
airport-ledger/src/main/resources/mapper/ledger/ScoreEventMapper.xml

@@ -62,6 +62,23 @@
62
         WHERE del_flag = '0'
62
         WHERE del_flag = '0'
63
     </sql>
63
     </sql>
64
 
64
 
65
+    <sql id="order_by">
66
+        <choose>
67
+            <when test="sorts != null and sorts.size() > 0">
68
+                order by
69
+                <foreach collection="sorts.entrySet()"
70
+                         index="field"
71
+                         item="dir"
72
+                         separator=",">
73
+                    ${field} ${dir}
74
+                </foreach>
75
+            </when>
76
+            <otherwise>
77
+                order by event_time desc
78
+            </otherwise>
79
+        </choose>
80
+    </sql>
81
+
65
     <select id="selectList" parameterType="com.sundot.airport.ledger.domain.ScoreEvent"
82
     <select id="selectList" parameterType="com.sundot.airport.ledger.domain.ScoreEvent"
66
             resultMap="ScoreEventResult">
83
             resultMap="ScoreEventResult">
67
         <include refid="selectVo"/>
84
         <include refid="selectVo"/>
@@ -96,7 +113,7 @@
96
         <if test="params != null and params.endTime != null and params.endTime != ''">
113
         <if test="params != null and params.endTime != null and params.endTime != ''">
97
             AND event_time &lt;= #{params.endTime}
114
             AND event_time &lt;= #{params.endTime}
98
         </if>
115
         </if>
99
-        ORDER BY event_time DESC, id DESC
116
+        <include refid="order_by"/>
100
     </select>
117
     </select>
101
 
118
 
102
 </mapper>
119
 </mapper>