Browse Source

证书管理

wangxx 1 month ago
parent
commit
973ff7aa2d

+ 132 - 0
airport-admin/src/main/java/com/sundot/airport/web/controller/ledger/LedgerCertificateInfoController.java

@@ -0,0 +1,132 @@
1
+package com.sundot.airport.web.controller.ledger;
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 com.sundot.airport.ledger.domain.LedgerCertificateInfo;
20
+import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
21
+import com.sundot.airport.common.utils.poi.ExcelUtil;
22
+import com.sundot.airport.common.core.page.TableDataInfo;
23
+import com.sundot.airport.ledger.utils.CertificateExcelImportUtil;
24
+import org.apache.poi.ss.usermodel.Workbook;
25
+import org.apache.poi.ss.usermodel.WorkbookFactory;
26
+import org.springframework.web.multipart.MultipartFile;
27
+
28
+/**
29
+ * 证书信息Controller
30
+ * 
31
+ * @author ruoyi
32
+ * @date 2026-06-29
33
+ */
34
+@RestController
35
+@RequestMapping("/ledger/certificate")
36
+public class LedgerCertificateInfoController extends BaseController {
37
+    @Autowired
38
+    private ILedgerCertificateInfoService certificateInfoService;
39
+
40
+    /**
41
+     * 查询证书信息列表
42
+     */
43
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:list')")
44
+    @GetMapping("/list")
45
+    public TableDataInfo list(LedgerCertificateInfo ledgerCertificateInfo) {
46
+        startPage();
47
+        List<LedgerCertificateInfo> list = certificateInfoService.selectCertificateInfoList(ledgerCertificateInfo);
48
+        return getDataTable(list);
49
+    }
50
+
51
+    /**
52
+     * 导出证书信息列表
53
+     */
54
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:export')")
55
+    @Log(title = "证书信息", businessType = BusinessType.EXPORT)
56
+    @PostMapping("/export")
57
+    public void export(HttpServletResponse response, LedgerCertificateInfo ledgerCertificateInfo) {
58
+        List<LedgerCertificateInfo> list = certificateInfoService.selectCertificateInfoList(ledgerCertificateInfo);
59
+        ExcelUtil<LedgerCertificateInfo> util = new ExcelUtil<LedgerCertificateInfo>(LedgerCertificateInfo.class);
60
+        util.exportExcel(response, list, "证书信息数据");
61
+    }
62
+
63
+    /**
64
+     * 获取证书信息详细信息
65
+     */
66
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:query')")
67
+    @GetMapping(value = "/{id}")
68
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
69
+        return success(certificateInfoService.selectCertificateInfoById(id));
70
+    }
71
+
72
+    /**
73
+     * 新增证书信息
74
+     */
75
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:add')")
76
+    @Log(title = "证书信息", businessType = BusinessType.INSERT)
77
+    @PostMapping
78
+    public AjaxResult add(@RequestBody LedgerCertificateInfo ledgerCertificateInfo) {
79
+        return toAjax(certificateInfoService.insertCertificateInfo(ledgerCertificateInfo));
80
+    }
81
+
82
+    /**
83
+     * 修改证书信息
84
+     */
85
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:edit')")
86
+    @Log(title = "证书信息", businessType = BusinessType.UPDATE)
87
+    @PutMapping
88
+    public AjaxResult edit(@RequestBody LedgerCertificateInfo ledgerCertificateInfo) {
89
+        return toAjax(certificateInfoService.updateCertificateInfo(ledgerCertificateInfo));
90
+    }
91
+
92
+    /**
93
+     * 删除证书信息
94
+     */
95
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:remove')")
96
+    @Log(title = "证书信息", businessType = BusinessType.DELETE)
97
+    @DeleteMapping("/{ids}")
98
+    public AjaxResult remove(@PathVariable Long[] ids) {
99
+        return toAjax(certificateInfoService.deleteCertificateInfoByIds(ids));
100
+    }
101
+
102
+    /**
103
+     * 导入证书数据(支持动态复审时间列)
104
+     *
105
+     */
106
+    @PreAuthorize("@ss.hasPermi('ledger:certificate:import')")
107
+    @Log(title = "证书信息", businessType = BusinessType.IMPORT)
108
+    @PostMapping("/importData")
109
+    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
110
+        // 使用自定义工具类解析Excel,支持动态复审时间列
111
+        Workbook workbook = WorkbookFactory.create(file.getInputStream());
112
+        List<LedgerCertificateInfo> certificateList = CertificateExcelImportUtil.parseCertificateExcel(workbook);
113
+        workbook.close();
114
+        
115
+        if (certificateList == null || certificateList.isEmpty()) {
116
+            return error("导入数据为空或格式不正确");
117
+        }
118
+        
119
+        String operName = getUsername();
120
+        String message = certificateInfoService.importCertificate(certificateList, updateSupport, operName);
121
+        return success(message);
122
+    }
123
+
124
+    /**
125
+     * 下载导入模板
126
+     */
127
+    @PostMapping("/importTemplate")
128
+    public void importTemplate(HttpServletResponse response) {
129
+        ExcelUtil<LedgerCertificateInfo> util = new ExcelUtil<LedgerCertificateInfo>(LedgerCertificateInfo.class);
130
+        util.importTemplateExcel(response, "证书信息数据");
131
+    }
132
+}

+ 349 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/domain/LedgerCertificateInfo.java

@@ -0,0 +1,349 @@
1
+package com.sundot.airport.ledger.domain;
2
+
3
+import java.math.BigDecimal;
4
+import java.util.Date;
5
+import java.util.List;
6
+
7
+import com.baomidou.mybatisplus.annotation.IdType;
8
+import com.baomidou.mybatisplus.annotation.TableField;
9
+import com.baomidou.mybatisplus.annotation.TableId;
10
+import com.baomidou.mybatisplus.annotation.TableName;
11
+import com.fasterxml.jackson.annotation.JsonFormat;
12
+import com.sundot.airport.common.annotation.Excel;
13
+import com.sundot.airport.common.core.domain.BaseEntity;
14
+import org.apache.commons.lang3.builder.ToStringBuilder;
15
+import org.apache.commons.lang3.builder.ToStringStyle;
16
+
17
+/**
18
+ * 证书信息对象 ledger_certificate_info
19
+ *
20
+ * @author ruoyi
21
+ * @date 2026-06-29
22
+ */
23
+@TableName("ledger_certificate_info")
24
+public class LedgerCertificateInfo extends BaseEntity {
25
+    private static final long serialVersionUID = 1L;
26
+
27
+    /**
28
+     * 主键ID
29
+     */
30
+    @TableId(type = IdType.AUTO)
31
+    private Long id;
32
+
33
+    /**
34
+     * 租户号
35
+     */
36
+    @Excel(name = "租户号")
37
+    private String tenantId;
38
+
39
+    /**
40
+     * 单位
41
+     */
42
+    @Excel(name = "单位")
43
+    private String unitName;
44
+
45
+    /**
46
+     * 用户ID(关联sys_user表)
47
+     */
48
+    @TableField("user_id")
49
+    private Long userId;
50
+
51
+    /**
52
+     * 姓名
53
+     */
54
+    @Excel(name = "姓名")
55
+    private String personName;
56
+
57
+    /**
58
+     * 性别
59
+     */
60
+    @Excel(name = "性别", readConverterExp = "男=男,女=女")
61
+    private String gender;
62
+
63
+    /**
64
+     * 出生日期
65
+     */
66
+    @JsonFormat(pattern = "yyyy-MM-dd")
67
+    @Excel(name = "出生日期", width = 30, dateFormat = "yyyy-MM-dd")
68
+    private Date birthDate;
69
+
70
+    /**
71
+     * 身份证号
72
+     */
73
+    @Excel(name = "身份证号")
74
+    private String idCard;
75
+
76
+    /**
77
+     * 证书等级
78
+     */
79
+    @Excel(name = "证书等级")
80
+    private String certLevel;
81
+
82
+    /**
83
+     * 发证日期
84
+     */
85
+    @JsonFormat(pattern = "yyyy-MM-dd")
86
+    @Excel(name = "发证日期", width = 30, dateFormat = "yyyy-MM-dd")
87
+    private Date issueDate;
88
+
89
+    /**
90
+     * 证书编号
91
+     */
92
+    @Excel(name = "证书编号")
93
+    private String certNo;
94
+
95
+    /**
96
+     * 理论考核成绩
97
+     */
98
+    @Excel(name = "理论考核成绩")
99
+    private BigDecimal theoryScore;
100
+
101
+    /**
102
+     * 实操考核成绩
103
+     */
104
+    @Excel(name = "实操考核成绩")
105
+    private BigDecimal practiceScore;
106
+
107
+    /**
108
+     * 评定成绩
109
+     */
110
+    @Excel(name = "评定成绩")
111
+    private BigDecimal evalScore;
112
+
113
+    /**
114
+     * 用工形式
115
+     */
116
+    @Excel(name = "用工形式")
117
+    private String employmentType;
118
+
119
+    /**
120
+     * 服务期(月)
121
+     */
122
+    @Excel(name = "服务期(月)")
123
+    private Integer serviceMonths;
124
+
125
+    /**
126
+     * 到期日期
127
+     */
128
+    @JsonFormat(pattern = "yyyy-MM-dd")
129
+    @Excel(name = "到期日期", width = 30, dateFormat = "yyyy-MM-dd")
130
+    private Date expiryDate;
131
+
132
+    /**
133
+     * 状态
134
+     */
135
+    @Excel(name = "状态")
136
+    private String status;
137
+
138
+    /**
139
+     * 到期天数
140
+     */
141
+    @Excel(name = "到期天数")
142
+    private Integer expireDays;
143
+
144
+    /**
145
+     * 备注
146
+     */
147
+    @Excel(name = "备注")
148
+    private String remark;
149
+
150
+    /**
151
+     * 复审记录列表(非数据库字段)
152
+     */
153
+    @TableField(exist = false)
154
+    private List<LedgerCertificateReviewRecord> reviewRecords;
155
+
156
+    public void setId(Long id) {
157
+        this.id = id;
158
+    }
159
+
160
+    public Long getId() {
161
+        return id;
162
+    }
163
+
164
+    public void setTenantId(String tenantId) {
165
+        this.tenantId = tenantId;
166
+    }
167
+
168
+    public String getTenantId() {
169
+        return tenantId;
170
+    }
171
+
172
+    public void setUnitName(String unitName) {
173
+        this.unitName = unitName;
174
+    }
175
+
176
+    public String getUnitName() {
177
+        return unitName;
178
+    }
179
+
180
+    public void setUserId(Long userId) {
181
+        this.userId = userId;
182
+    }
183
+
184
+    public Long getUserId() {
185
+        return userId;
186
+    }
187
+
188
+    public void setPersonName(String personName) {
189
+        this.personName = personName;
190
+    }
191
+
192
+    public String getPersonName() {
193
+        return personName;
194
+    }
195
+
196
+    public void setGender(String gender) {
197
+        this.gender = gender;
198
+    }
199
+
200
+    public String getGender() {
201
+        return gender;
202
+    }
203
+
204
+    public void setBirthDate(Date birthDate) {
205
+        this.birthDate = birthDate;
206
+    }
207
+
208
+    public Date getBirthDate() {
209
+        return birthDate;
210
+    }
211
+
212
+    public void setIdCard(String idCard) {
213
+        this.idCard = idCard;
214
+    }
215
+
216
+    public String getIdCard() {
217
+        return idCard;
218
+    }
219
+
220
+    public void setCertLevel(String certLevel) {
221
+        this.certLevel = certLevel;
222
+    }
223
+
224
+    public String getCertLevel() {
225
+        return certLevel;
226
+    }
227
+
228
+    public void setIssueDate(Date issueDate) {
229
+        this.issueDate = issueDate;
230
+    }
231
+
232
+    public Date getIssueDate() {
233
+        return issueDate;
234
+    }
235
+
236
+    public void setCertNo(String certNo) {
237
+        this.certNo = certNo;
238
+    }
239
+
240
+    public String getCertNo() {
241
+        return certNo;
242
+    }
243
+
244
+    public void setTheoryScore(BigDecimal theoryScore) {
245
+        this.theoryScore = theoryScore;
246
+    }
247
+
248
+    public BigDecimal getTheoryScore() {
249
+        return theoryScore;
250
+    }
251
+
252
+    public void setPracticeScore(BigDecimal practiceScore) {
253
+        this.practiceScore = practiceScore;
254
+    }
255
+
256
+    public BigDecimal getPracticeScore() {
257
+        return practiceScore;
258
+    }
259
+
260
+    public void setEvalScore(BigDecimal evalScore) {
261
+        this.evalScore = evalScore;
262
+    }
263
+
264
+    public BigDecimal getEvalScore() {
265
+        return evalScore;
266
+    }
267
+
268
+    public void setEmploymentType(String employmentType) {
269
+        this.employmentType = employmentType;
270
+    }
271
+
272
+    public String getEmploymentType() {
273
+        return employmentType;
274
+    }
275
+
276
+    public void setServiceMonths(Integer serviceMonths) {
277
+        this.serviceMonths = serviceMonths;
278
+    }
279
+
280
+    public Integer getServiceMonths() {
281
+        return serviceMonths;
282
+    }
283
+
284
+    public void setExpiryDate(Date expiryDate) {
285
+        this.expiryDate = expiryDate;
286
+    }
287
+
288
+    public Date getExpiryDate() {
289
+        return expiryDate;
290
+    }
291
+
292
+    public void setStatus(String status) {
293
+        this.status = status;
294
+    }
295
+
296
+    public String getStatus() {
297
+        return status;
298
+    }
299
+
300
+    public void setExpireDays(Integer expireDays) {
301
+        this.expireDays = expireDays;
302
+    }
303
+
304
+    public Integer getExpireDays() {
305
+        return expireDays;
306
+    }
307
+
308
+    public void setRemark(String remark) {
309
+        this.remark = remark;
310
+    }
311
+
312
+    public String getRemark() {
313
+        return remark;
314
+    }
315
+
316
+    public void setReviewRecords(List<LedgerCertificateReviewRecord> reviewRecords) {
317
+        this.reviewRecords = reviewRecords;
318
+    }
319
+
320
+    public List<LedgerCertificateReviewRecord> getReviewRecords() {
321
+        return reviewRecords;
322
+    }
323
+
324
+    @Override
325
+    public String toString() {
326
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
327
+                .append("id", getId())
328
+                .append("tenantId", getTenantId())
329
+                .append("unitName", getUnitName())
330
+                .append("userId", getUserId())
331
+                .append("personName", getPersonName())
332
+                .append("gender", getGender())
333
+                .append("birthDate", getBirthDate())
334
+                .append("idCard", getIdCard())
335
+                .append("certLevel", getCertLevel())
336
+                .append("issueDate", getIssueDate())
337
+                .append("certNo", getCertNo())
338
+                .append("theoryScore", getTheoryScore())
339
+                .append("practiceScore", getPracticeScore())
340
+                .append("evalScore", getEvalScore())
341
+                .append("employmentType", getEmploymentType())
342
+                .append("serviceMonths", getServiceMonths())
343
+                .append("expiryDate", getExpiryDate())
344
+                .append("status", getStatus())
345
+                .append("expireDays", getExpireDays())
346
+                .append("remark", getRemark())
347
+                .toString();
348
+    }
349
+}

+ 135 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/domain/LedgerCertificateReviewRecord.java

@@ -0,0 +1,135 @@
1
+package com.sundot.airport.ledger.domain;
2
+
3
+import java.util.Date;
4
+
5
+import com.baomidou.mybatisplus.annotation.IdType;
6
+import com.baomidou.mybatisplus.annotation.TableId;
7
+import com.baomidou.mybatisplus.annotation.TableName;
8
+import com.fasterxml.jackson.annotation.JsonFormat;
9
+import com.sundot.airport.common.annotation.Excel;
10
+import com.sundot.airport.common.core.domain.BaseEntity;
11
+import org.apache.commons.lang3.builder.ToStringBuilder;
12
+import org.apache.commons.lang3.builder.ToStringStyle;
13
+
14
+/**
15
+ * 证书复审记录对象 certificate_review_record
16
+ *
17
+ * @author ruoyi
18
+ * @date 2026-06-29
19
+ */
20
+@TableName("ledger_certificate_review_record")
21
+public class LedgerCertificateReviewRecord extends BaseEntity {
22
+    private static final long serialVersionUID = 1L;
23
+
24
+    /**
25
+     * 主键ID
26
+     */
27
+    @TableId(type = IdType.AUTO)
28
+    private Long id;
29
+
30
+    /**
31
+     * 证书ID(关联certificate_info.id)
32
+     */
33
+    @Excel(name = "证书ID")
34
+    private Long certId;
35
+
36
+    /**
37
+     * 复审次序(1第一次 2第二次...)
38
+     */
39
+    @Excel(name = "复审次序")
40
+    private Integer reviewSeq;
41
+
42
+    /**
43
+     * 复审时间
44
+     */
45
+    @JsonFormat(pattern = "yyyy-MM-dd")
46
+    @Excel(name = "复审时间", width = 30, dateFormat = "yyyy-MM-dd")
47
+    private Date reviewTime;
48
+
49
+    /**
50
+     * 复审结果
51
+     */
52
+    @Excel(name = "复审结果")
53
+    private String reviewResult;
54
+
55
+    /**
56
+     * 复审人
57
+     */
58
+    @Excel(name = "复审人")
59
+    private String reviewer;
60
+
61
+    /**
62
+     * 备注
63
+     */
64
+    @Excel(name = "备注")
65
+    private String remark;
66
+
67
+    public void setId(Long id) {
68
+        this.id = id;
69
+    }
70
+
71
+    public Long getId() {
72
+        return id;
73
+    }
74
+
75
+    public void setCertId(Long certId) {
76
+        this.certId = certId;
77
+    }
78
+
79
+    public Long getCertId() {
80
+        return certId;
81
+    }
82
+
83
+    public void setReviewSeq(Integer reviewSeq) {
84
+        this.reviewSeq = reviewSeq;
85
+    }
86
+
87
+    public Integer getReviewSeq() {
88
+        return reviewSeq;
89
+    }
90
+
91
+    public void setReviewTime(Date reviewTime) {
92
+        this.reviewTime = reviewTime;
93
+    }
94
+
95
+    public Date getReviewTime() {
96
+        return reviewTime;
97
+    }
98
+
99
+    public void setReviewResult(String reviewResult) {
100
+        this.reviewResult = reviewResult;
101
+    }
102
+
103
+    public String getReviewResult() {
104
+        return reviewResult;
105
+    }
106
+
107
+    public void setReviewer(String reviewer) {
108
+        this.reviewer = reviewer;
109
+    }
110
+
111
+    public String getReviewer() {
112
+        return reviewer;
113
+    }
114
+
115
+    public void setRemark(String remark) {
116
+        this.remark = remark;
117
+    }
118
+
119
+    public String getRemark() {
120
+        return remark;
121
+    }
122
+
123
+    @Override
124
+    public String toString() {
125
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
126
+                .append("id", getId())
127
+                .append("certId", getCertId())
128
+                .append("reviewSeq", getReviewSeq())
129
+                .append("reviewTime", getReviewTime())
130
+                .append("reviewResult", getReviewResult())
131
+                .append("reviewer", getReviewer())
132
+                .append("remark", getRemark())
133
+                .toString();
134
+    }
135
+}

+ 231 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/dto/LedgerCertificateImportDTO.java

@@ -0,0 +1,231 @@
1
+package com.sundot.airport.ledger.dto;
2
+
3
+import java.util.Date;
4
+
5
+import com.sundot.airport.common.annotation.Excel;
6
+import com.sundot.airport.common.core.domain.BaseEntity;
7
+
8
+/**
9
+ * 证书信息导入对象(用于Excel导入)
10
+ * 
11
+ * @author ruoyi
12
+ * @date 2026-06-29
13
+ */
14
+public class LedgerCertificateImportDTO extends BaseEntity {
15
+    
16
+    @Excel(name = "序号")
17
+    private Integer rowNum;
18
+    
19
+    @Excel(name = "单位")
20
+    private String unitName;
21
+    
22
+    @Excel(name = "姓名")
23
+    private String personName;
24
+    
25
+    @Excel(name = "性别")
26
+    private String gender;
27
+    
28
+    @Excel(name = "出生日期", dateFormat = "yyyy-MM-dd")
29
+    private Date birthDate;
30
+    
31
+    @Excel(name = "身份证号")
32
+    private String idCard;
33
+    
34
+    @Excel(name = "证书等级")
35
+    private String certLevel;
36
+    
37
+    @Excel(name = "发证日期", dateFormat = "yyyy-MM-dd")
38
+    private Date issueDate;
39
+    
40
+    @Excel(name = "证书编号")
41
+    private String certNo;
42
+    
43
+    @Excel(name = "理论考核成绩")
44
+    private Double theoryScore;
45
+    
46
+    @Excel(name = "实操考核成绩")
47
+    private Double practiceScore;
48
+    
49
+    @Excel(name = "评定成绩")
50
+    private Double evalScore;
51
+    
52
+    @Excel(name = "用工形式")
53
+    private String employmentType;
54
+    
55
+    @Excel(name = "服务期(月)")
56
+    private Integer serviceMonths;
57
+    
58
+    @Excel(name = "到期日期", dateFormat = "yyyy-MM-dd")
59
+    private Date expiryDate;
60
+    
61
+    @Excel(name = "状态")
62
+    private String status;
63
+    
64
+    @Excel(name = "到期天数")
65
+    private Integer expireDays;
66
+    
67
+    @Excel(name = "备注")
68
+    private String remark;
69
+    
70
+    // 注意:复审时间不在这里定义,因为数量不固定
71
+    // 在导入时需要动态解析"第1次复审时间"、"第2次复审时间"等列
72
+    
73
+    /**
74
+     * 动态字段:存储所有复审时间
75
+     * Key: 复审次序(1,2,3...)
76
+     * Value: 复审时间
77
+     */
78
+    private java.util.Map<Integer, Date> reviewTimeMap;
79
+
80
+    public Integer getRowNum() {
81
+        return rowNum;
82
+    }
83
+
84
+    public void setRowNum(Integer rowNum) {
85
+        this.rowNum = rowNum;
86
+    }
87
+
88
+    public String getUnitName() {
89
+        return unitName;
90
+    }
91
+
92
+    public void setUnitName(String unitName) {
93
+        this.unitName = unitName;
94
+    }
95
+
96
+    public String getPersonName() {
97
+        return personName;
98
+    }
99
+
100
+    public void setPersonName(String personName) {
101
+        this.personName = personName;
102
+    }
103
+
104
+    public String getGender() {
105
+        return gender;
106
+    }
107
+
108
+    public void setGender(String gender) {
109
+        this.gender = gender;
110
+    }
111
+
112
+    public Date getBirthDate() {
113
+        return birthDate;
114
+    }
115
+
116
+    public void setBirthDate(Date birthDate) {
117
+        this.birthDate = birthDate;
118
+    }
119
+
120
+    public String getIdCard() {
121
+        return idCard;
122
+    }
123
+
124
+    public void setIdCard(String idCard) {
125
+        this.idCard = idCard;
126
+    }
127
+
128
+    public String getCertLevel() {
129
+        return certLevel;
130
+    }
131
+
132
+    public void setCertLevel(String certLevel) {
133
+        this.certLevel = certLevel;
134
+    }
135
+
136
+    public Date getIssueDate() {
137
+        return issueDate;
138
+    }
139
+
140
+    public void setIssueDate(Date issueDate) {
141
+        this.issueDate = issueDate;
142
+    }
143
+
144
+    public String getCertNo() {
145
+        return certNo;
146
+    }
147
+
148
+    public void setCertNo(String certNo) {
149
+        this.certNo = certNo;
150
+    }
151
+
152
+    public Double getTheoryScore() {
153
+        return theoryScore;
154
+    }
155
+
156
+    public void setTheoryScore(Double theoryScore) {
157
+        this.theoryScore = theoryScore;
158
+    }
159
+
160
+    public Double getPracticeScore() {
161
+        return practiceScore;
162
+    }
163
+
164
+    public void setPracticeScore(Double practiceScore) {
165
+        this.practiceScore = practiceScore;
166
+    }
167
+
168
+    public Double getEvalScore() {
169
+        return evalScore;
170
+    }
171
+
172
+    public void setEvalScore(Double evalScore) {
173
+        this.evalScore = evalScore;
174
+    }
175
+
176
+    public String getEmploymentType() {
177
+        return employmentType;
178
+    }
179
+
180
+    public void setEmploymentType(String employmentType) {
181
+        this.employmentType = employmentType;
182
+    }
183
+
184
+    public Integer getServiceMonths() {
185
+        return serviceMonths;
186
+    }
187
+
188
+    public void setServiceMonths(Integer serviceMonths) {
189
+        this.serviceMonths = serviceMonths;
190
+    }
191
+
192
+    public Date getExpiryDate() {
193
+        return expiryDate;
194
+    }
195
+
196
+    public void setExpiryDate(Date expiryDate) {
197
+        this.expiryDate = expiryDate;
198
+    }
199
+
200
+    public String getStatus() {
201
+        return status;
202
+    }
203
+
204
+    public void setStatus(String status) {
205
+        this.status = status;
206
+    }
207
+
208
+    public Integer getExpireDays() {
209
+        return expireDays;
210
+    }
211
+
212
+    public void setExpireDays(Integer expireDays) {
213
+        this.expireDays = expireDays;
214
+    }
215
+
216
+    public String getRemark() {
217
+        return remark;
218
+    }
219
+
220
+    public void setRemark(String remark) {
221
+        this.remark = remark;
222
+    }
223
+
224
+    public java.util.Map<Integer, Date> getReviewTimeMap() {
225
+        return reviewTimeMap;
226
+    }
227
+
228
+    public void setReviewTimeMap(java.util.Map<Integer, Date> reviewTimeMap) {
229
+        this.reviewTimeMap = reviewTimeMap;
230
+    }
231
+}

+ 86 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/mapper/LedgerCertificateInfoMapper.java

@@ -0,0 +1,86 @@
1
+package com.sundot.airport.ledger.mapper;
2
+
3
+import java.util.List;
4
+import org.apache.ibatis.annotations.Param;
5
+import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
6
+
7
+/**
8
+ * 证书信息Mapper接口
9
+ * 
10
+ * @author ruoyi
11
+ * @date 2026-06-29
12
+ */
13
+public interface LedgerCertificateInfoMapper {
14
+    /**
15
+     * 查询证书信息
16
+     * 
17
+     * @param id 证书信息主键
18
+     * @return 证书信息
19
+     */
20
+    public LedgerCertificateInfo selectCertificateInfoById(Long id);
21
+
22
+    /**
23
+     * 查询证书信息列表
24
+     * 
25
+     * @param ledgerCertificateInfo 证书信息
26
+     * @return 证书信息集合
27
+     */
28
+    public List<LedgerCertificateInfo> selectCertificateInfoList(LedgerCertificateInfo ledgerCertificateInfo);
29
+
30
+    /**
31
+     * 新增证书信息
32
+     * 
33
+     * @param ledgerCertificateInfo 证书信息
34
+     * @return 结果
35
+     */
36
+    public int insertCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo);
37
+
38
+    /**
39
+     * 修改证书信息
40
+     * 
41
+     * @param ledgerCertificateInfo 证书信息
42
+     * @return 结果
43
+     */
44
+    public int updateCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo);
45
+
46
+    /**
47
+     * 删除证书信息
48
+     * 
49
+     * @param id 证书信息主键
50
+     * @return 结果
51
+     */
52
+    public int deleteCertificateInfoById(Long id);
53
+
54
+    /**
55
+     * 批量删除证书信息
56
+     * 
57
+     * @param ids 需要删除的数据主键集合
58
+     * @return 结果
59
+     */
60
+    public int deleteCertificateInfoByIds(Long[] ids);
61
+
62
+    /**
63
+     * 根据身份证号查询证书信息
64
+     * 
65
+     * @param idCard 身份证号
66
+     * @return 证书信息
67
+     */
68
+    public LedgerCertificateInfo selectCertificateInfoByIdCard(String idCard);
69
+
70
+    /**
71
+     * 根据证书编号查询证书信息
72
+     * 
73
+     * @param certNo 证书编号
74
+     * @return 证书信息
75
+     */
76
+    public LedgerCertificateInfo selectCertificateInfoByCertNo(String certNo);
77
+
78
+    /**
79
+     * 根据用户ID和证书编号查询证书信息
80
+     * 
81
+     * @param userId 用户ID
82
+     * @param certNo 证书编号
83
+     * @return 证书信息
84
+     */
85
+    public LedgerCertificateInfo selectCertificateInfoByUserIdAndCertNo(@Param("userId") Long userId, @Param("certNo") String certNo);
86
+}

+ 76 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/mapper/LedgerCertificateReviewRecordMapper.java

@@ -0,0 +1,76 @@
1
+package com.sundot.airport.ledger.mapper;
2
+
3
+import java.util.List;
4
+import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
5
+
6
+/**
7
+ * 证书复审记录Mapper接口
8
+ * 
9
+ * @author ruoyi
10
+ * @date 2026-06-29
11
+ */
12
+public interface LedgerCertificateReviewRecordMapper {
13
+    /**
14
+     * 查询证书复审记录
15
+     * 
16
+     * @param id 证书复审记录主键
17
+     * @return 证书复审记录
18
+     */
19
+    public LedgerCertificateReviewRecord selectCertificateReviewRecordById(Long id);
20
+
21
+    /**
22
+     * 查询证书复审记录列表
23
+     * 
24
+     * @param ledgerCertificateReviewRecord 证书复审记录
25
+     * @return 证书复审记录集合
26
+     */
27
+    public List<LedgerCertificateReviewRecord> selectCertificateReviewRecordList(LedgerCertificateReviewRecord ledgerCertificateReviewRecord);
28
+
29
+    /**
30
+     * 根据证书ID查询复审记录列表
31
+     * 
32
+     * @param certId 证书ID
33
+     * @return 证书复审记录集合
34
+     */
35
+    public List<LedgerCertificateReviewRecord> selectCertificateReviewRecordByCertId(Long certId);
36
+
37
+    /**
38
+     * 新增证书复审记录
39
+     * 
40
+     * @param ledgerCertificateReviewRecord 证书复审记录
41
+     * @return 结果
42
+     */
43
+    public int insertCertificateReviewRecord(LedgerCertificateReviewRecord ledgerCertificateReviewRecord);
44
+
45
+    /**
46
+     * 修改证书复审记录
47
+     * 
48
+     * @param ledgerCertificateReviewRecord 证书复审记录
49
+     * @return 结果
50
+     */
51
+    public int updateCertificateReviewRecord(LedgerCertificateReviewRecord ledgerCertificateReviewRecord);
52
+
53
+    /**
54
+     * 删除证书复审记录
55
+     * 
56
+     * @param id 证书复审记录主键
57
+     * @return 结果
58
+     */
59
+    public int deleteCertificateReviewRecordById(Long id);
60
+
61
+    /**
62
+     * 批量删除证书复审记录
63
+     * 
64
+     * @param ids 需要删除的数据主键集合
65
+     * @return 结果
66
+     */
67
+    public int deleteCertificateReviewRecordByIds(Long[] ids);
68
+
69
+    /**
70
+     * 根据证书ID删除所有复审记录
71
+     * 
72
+     * @param certId 证书ID
73
+     * @return 结果
74
+     */
75
+    public int deleteCertificateReviewRecordByCertId(Long certId);
76
+}

+ 70 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/ILedgerCertificateInfoService.java

@@ -0,0 +1,70 @@
1
+package com.sundot.airport.ledger.service;
2
+
3
+import java.util.List;
4
+import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
5
+
6
+/**
7
+ * 证书信息Service接口
8
+ * 
9
+ * @author ruoyi
10
+ * @date 2026-06-29
11
+ */
12
+public interface ILedgerCertificateInfoService {
13
+    /**
14
+     * 查询证书信息
15
+     * 
16
+     * @param id 证书信息主键
17
+     * @return 证书信息
18
+     */
19
+    public LedgerCertificateInfo selectCertificateInfoById(Long id);
20
+
21
+    /**
22
+     * 查询证书信息列表
23
+     * 
24
+     * @param ledgerCertificateInfo 证书信息
25
+     * @return 证书信息集合
26
+     */
27
+    public List<LedgerCertificateInfo> selectCertificateInfoList(LedgerCertificateInfo ledgerCertificateInfo);
28
+
29
+    /**
30
+     * 新增证书信息
31
+     * 
32
+     * @param ledgerCertificateInfo 证书信息
33
+     * @return 结果
34
+     */
35
+    public int insertCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo);
36
+
37
+    /**
38
+     * 修改证书信息
39
+     * 
40
+     * @param ledgerCertificateInfo 证书信息
41
+     * @return 结果
42
+     */
43
+    public int updateCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo);
44
+
45
+    /**
46
+     * 批量删除证书信息
47
+     * 
48
+     * @param ids 需要删除的证书信息主键集合
49
+     * @return 结果
50
+     */
51
+    public int deleteCertificateInfoByIds(Long[] ids);
52
+
53
+    /**
54
+     * 删除证书信息信息
55
+     * 
56
+     * @param id 证书信息主键
57
+     * @return 结果
58
+     */
59
+    public int deleteCertificateInfoById(Long id);
60
+
61
+    /**
62
+     * 导入证书数据
63
+     * 
64
+     * @param certificateList 证书数据列表
65
+     * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
66
+     * @param operName 操作用户
67
+     * @return 结果
68
+     */
69
+    public String importCertificate(List<LedgerCertificateInfo> certificateList, Boolean isUpdateSupport, String operName);
70
+}

+ 76 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/ILedgerCertificateReviewRecordService.java

@@ -0,0 +1,76 @@
1
+package com.sundot.airport.ledger.service;
2
+
3
+import java.util.List;
4
+import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
5
+
6
+/**
7
+ * 证书复审记录Service接口
8
+ * 
9
+ * @author ruoyi
10
+ * @date 2026-06-29
11
+ */
12
+public interface ILedgerCertificateReviewRecordService {
13
+    /**
14
+     * 查询证书复审记录
15
+     * 
16
+     * @param id 证书复审记录主键
17
+     * @return 证书复审记录
18
+     */
19
+    public LedgerCertificateReviewRecord selectCertificateReviewRecordById(Long id);
20
+
21
+    /**
22
+     * 查询证书复审记录列表
23
+     * 
24
+     * @param ledgerCertificateReviewRecord 证书复审记录
25
+     * @return 证书复审记录集合
26
+     */
27
+    public List<LedgerCertificateReviewRecord> selectCertificateReviewRecordList(LedgerCertificateReviewRecord ledgerCertificateReviewRecord);
28
+
29
+    /**
30
+     * 根据证书ID查询复审记录列表
31
+     * 
32
+     * @param certId 证书ID
33
+     * @return 证书复审记录集合
34
+     */
35
+    public List<LedgerCertificateReviewRecord> selectCertificateReviewRecordByCertId(Long certId);
36
+
37
+    /**
38
+     * 新增证书复审记录
39
+     * 
40
+     * @param ledgerCertificateReviewRecord 证书复审记录
41
+     * @return 结果
42
+     */
43
+    public int insertCertificateReviewRecord(LedgerCertificateReviewRecord ledgerCertificateReviewRecord);
44
+
45
+    /**
46
+     * 修改证书复审记录
47
+     * 
48
+     * @param ledgerCertificateReviewRecord 证书复审记录
49
+     * @return 结果
50
+     */
51
+    public int updateCertificateReviewRecord(LedgerCertificateReviewRecord ledgerCertificateReviewRecord);
52
+
53
+    /**
54
+     * 批量删除证书复审记录
55
+     * 
56
+     * @param ids 需要删除的证书复审记录主键集合
57
+     * @return 结果
58
+     */
59
+    public int deleteCertificateReviewRecordByIds(Long[] ids);
60
+
61
+    /**
62
+     * 删除证书复审记录信息
63
+     * 
64
+     * @param id 证书复审记录主键
65
+     * @return 结果
66
+     */
67
+    public int deleteCertificateReviewRecordById(Long id);
68
+
69
+    /**
70
+     * 根据证书ID删除所有复审记录
71
+     * 
72
+     * @param certId 证书ID
73
+     * @return 结果
74
+     */
75
+    public int deleteCertificateReviewRecordByCertId(Long certId);
76
+}

+ 380 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/impl/LedgerLedgerCertificateInfoServiceImpl.java

@@ -0,0 +1,380 @@
1
+package com.sundot.airport.ledger.service.impl;
2
+
3
+import java.util.ArrayList;
4
+import java.util.HashMap;
5
+import java.util.List;
6
+import java.util.Map;
7
+import java.util.stream.Collectors;
8
+
9
+import org.springframework.beans.factory.annotation.Autowired;
10
+import org.springframework.stereotype.Service;
11
+import org.springframework.transaction.annotation.Transactional;
12
+import com.sundot.airport.common.core.domain.entity.SysUser;
13
+import com.sundot.airport.common.utils.DateUtils;
14
+import com.sundot.airport.ledger.mapper.LedgerCertificateInfoMapper;
15
+import com.sundot.airport.ledger.mapper.LedgerCertificateReviewRecordMapper;
16
+import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
17
+import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
18
+import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
19
+import com.sundot.airport.system.service.ISysUserService;
20
+
21
+/**
22
+ * 证书信息Service业务层处理
23
+ * 
24
+ * @author ruoyi
25
+ * @date 2026-06-29
26
+ */
27
+@Service
28
+public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificateInfoService {
29
+    @Autowired
30
+    private LedgerCertificateInfoMapper ledgerCertificateInfoMapper;
31
+
32
+    @Autowired
33
+    private LedgerCertificateReviewRecordMapper ledgerCertificateReviewRecordMapper;
34
+
35
+    @Autowired
36
+    private ISysUserService sysUserService;
37
+
38
+    /**
39
+     * 查询证书信息
40
+     * 
41
+     * @param id 证书信息主键
42
+     * @return 证书信息
43
+     */
44
+    @Override
45
+    public LedgerCertificateInfo selectCertificateInfoById(Long id) {
46
+        LedgerCertificateInfo ledgerCertificateInfo = ledgerCertificateInfoMapper.selectCertificateInfoById(id);
47
+        if (ledgerCertificateInfo != null) {
48
+            // 查询复审记录
49
+            List<LedgerCertificateReviewRecord> reviewRecords = ledgerCertificateReviewRecordMapper.selectCertificateReviewRecordByCertId(id);
50
+            ledgerCertificateInfo.setReviewRecords(reviewRecords);
51
+        }
52
+        return ledgerCertificateInfo;
53
+    }
54
+
55
+    /**
56
+     * 查询证书信息列表
57
+     * 
58
+     * @param ledgerCertificateInfo 证书信息
59
+     * @return 证书信息
60
+     */
61
+    @Override
62
+    public List<LedgerCertificateInfo> selectCertificateInfoList(LedgerCertificateInfo ledgerCertificateInfo) {
63
+        return ledgerCertificateInfoMapper.selectCertificateInfoList(ledgerCertificateInfo);
64
+    }
65
+
66
+    /**
67
+     * 新增证书信息
68
+     * 
69
+     * @param ledgerCertificateInfo 证书信息
70
+     * @return 结果
71
+     */
72
+    @Override
73
+    @Transactional
74
+    public int insertCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo) {
75
+        ledgerCertificateInfo.setCreateTime(DateUtils.getNowDate());
76
+        int rows = ledgerCertificateInfoMapper.insertCertificateInfo(ledgerCertificateInfo);
77
+        
78
+        // 保存复审记录
79
+        saveReviewRecords(ledgerCertificateInfo.getId(), ledgerCertificateInfo.getReviewRecords());
80
+        
81
+        return rows;
82
+    }
83
+
84
+    /**
85
+     * 修改证书信息
86
+     * 
87
+     * @param ledgerCertificateInfo 证书信息
88
+     * @return 结果
89
+     */
90
+    @Override
91
+    @Transactional
92
+    public int updateCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo) {
93
+        ledgerCertificateInfo.setUpdateTime(DateUtils.getNowDate());
94
+        int rows = ledgerCertificateInfoMapper.updateCertificateInfo(ledgerCertificateInfo);
95
+        
96
+        // 先删除旧的复审记录,再保存新的
97
+        ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(ledgerCertificateInfo.getId());
98
+        saveReviewRecords(ledgerCertificateInfo.getId(), ledgerCertificateInfo.getReviewRecords());
99
+        
100
+        return rows;
101
+    }
102
+
103
+    /**
104
+     * 批量删除证书信息
105
+     * 
106
+     * @param ids 需要删除的证书信息主键
107
+     * @return 结果
108
+     */
109
+    @Override
110
+    @Transactional
111
+    public int deleteCertificateInfoByIds(Long[] ids) {
112
+        // 删除复审记录
113
+        for (Long id : ids) {
114
+            ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(id);
115
+        }
116
+        return ledgerCertificateInfoMapper.deleteCertificateInfoByIds(ids);
117
+    }
118
+
119
+    /**
120
+     * 删除证书信息信息
121
+     * 
122
+     * @param id 证书信息主键
123
+     * @return 结果
124
+     */
125
+    @Override
126
+    @Transactional
127
+    public int deleteCertificateInfoById(Long id) {
128
+        // 删除复审记录
129
+        ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(id);
130
+        return ledgerCertificateInfoMapper.deleteCertificateInfoById(id);
131
+    }
132
+
133
+    /**
134
+     * 导入证书数据
135
+     * 
136
+     * @param certificateList 证书数据列表
137
+     * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
138
+     * @param operName 操作用户
139
+     * @return 结果
140
+     */
141
+    @Override
142
+    @Transactional
143
+    public String importCertificate(List<LedgerCertificateInfo> certificateList, Boolean isUpdateSupport, String operName) {
144
+        if (certificateList == null || certificateList.isEmpty()) {
145
+            throw new RuntimeException("导入证书数据不能为空!");
146
+        }
147
+        
148
+        int successNum = 0;
149
+        int failureNum = 0;
150
+        StringBuilder successMsg = new StringBuilder();
151
+        StringBuilder failureMsg = new StringBuilder();
152
+        
153
+        // 第一步: 收集所有姓名,批量查询用户信息
154
+        List<String> personNames = certificateList.stream()
155
+                .map(LedgerCertificateInfo::getPersonName)
156
+                .filter(name -> name != null && !name.trim().isEmpty())
157
+                .distinct()
158
+                .collect(Collectors.toList());
159
+        
160
+        // 批量查询用户信息
161
+        List<SysUser> users = sysUserService.selectUsersByNames(personNames);
162
+        
163
+        // 构建姓名到用户的映射 Map<姓名, SysUser>
164
+        Map<String, SysUser> userMap = new HashMap<>();
165
+        for (SysUser user : users) {
166
+            // 优先使用 nickName(用户名称),如果没有则使用 userName(登录名称)
167
+            String key = user.getNickName() != null && !user.getNickName().isEmpty() 
168
+                    ? user.getNickName() : user.getUserName();
169
+            userMap.put(key, user);
170
+        }
171
+        
172
+        // 第二步: 找出未找到用户的姓名
173
+        List<String> notFoundNames = new ArrayList<>();
174
+        for (String name : personNames) {
175
+            if (!userMap.containsKey(name)) {
176
+                notFoundNames.add(name);
177
+            }
178
+        }
179
+        
180
+        // 如果有未找到的用户,报错提醒
181
+        if (!notFoundNames.isEmpty()) {
182
+            throw new RuntimeException("以下人员未在系统中找到:" + String.join("、", notFoundNames));
183
+        }
184
+        
185
+        // 第三步: 为每个证书设置 userId
186
+        for (LedgerCertificateInfo certificate : certificateList) {
187
+            String personName = certificate.getPersonName();
188
+            SysUser user = userMap.get(personName);
189
+            if (user != null) {
190
+                certificate.setUserId(user.getUserId());
191
+            }
192
+        }
193
+        
194
+        // 第四步: 批量查询已存在的证书信息(根据 userId 和 certNo)
195
+        Map<String, LedgerCertificateInfo> existingCertMap = new HashMap<>();
196
+        for (LedgerCertificateInfo certificate : certificateList) {
197
+            if (certificate.getUserId() != null && certificate.getCertNo() != null) {
198
+                LedgerCertificateInfo existCert = ledgerCertificateInfoMapper.selectCertificateInfoByUserIdAndCertNo(
199
+                        certificate.getUserId(), certificate.getCertNo());
200
+                if (existCert != null) {
201
+                    String key = certificate.getUserId() + "_" + certificate.getCertNo();
202
+                    existingCertMap.put(key, existCert);
203
+                }
204
+            }
205
+        }
206
+        
207
+        // 第五步: 处理每个证书的导入(新增或更新)
208
+        for (LedgerCertificateInfo certificate : certificateList) {
209
+            try {
210
+                String key = certificate.getUserId() + "_" + certificate.getCertNo();
211
+                LedgerCertificateInfo existCert = existingCertMap.get(key);
212
+                
213
+                if (existCert != null) {
214
+                    // 存在则更新
215
+                    if (isUpdateSupport) {
216
+                        certificate.setId(existCert.getId());
217
+                        certificate.setUpdateBy(operName);
218
+                        ledgerCertificateInfoMapper.updateCertificateInfo(certificate);
219
+                        
220
+                        // 更新复审记录
221
+                        ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(existCert.getId());
222
+                        saveReviewRecords(existCert.getId(), certificate.getReviewRecords());
223
+                        
224
+                        successNum++;
225
+                        successMsg.append("<br/>").append(successNum).append("、")
226
+                                .append(certificate.getPersonName()).append(" 的证书编号 ")
227
+                                .append(certificate.getCertNo()).append(" 更新成功");
228
+                    } else {
229
+                        failureNum++;
230
+                        failureMsg.append("<br/>").append(failureNum).append("、")
231
+                                .append(certificate.getPersonName()).append(" 的证书编号 ")
232
+                                .append(certificate.getCertNo()).append(" 已存在");
233
+                    }
234
+                } else {
235
+                    // 不存在则新增
236
+                    certificate.setCreateBy(operName);
237
+                    ledgerCertificateInfoMapper.insertCertificateInfo(certificate);
238
+                    
239
+                    // 保存复审记录
240
+                    saveReviewRecords(certificate.getId(), certificate.getReviewRecords());
241
+                    
242
+                    successNum++;
243
+                    successMsg.append("<br/>").append(successNum).append("、")
244
+                            .append(certificate.getPersonName()).append(" 的证书编号 ")
245
+                            .append(certificate.getCertNo()).append(" 导入成功");
246
+                }
247
+                
248
+                // 第六步: 同步更新用户表的证书等级(5<4<3<2<1,数字越小等级越高)
249
+                syncUserQualificationLevel(certificate.getUserId(), certificate.getCertLevel());
250
+                
251
+            } catch (Exception e) {
252
+                failureNum++;
253
+                String msg = "<br/>" + failureNum + "、" + certificate.getPersonName() + " 的证书编号 " 
254
+                        + certificate.getCertNo() + " 导入失败:";
255
+                failureMsg.append(msg + e.getMessage());
256
+            }
257
+        }
258
+        
259
+        if (failureNum > 0) {
260
+            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
261
+            throw new RuntimeException(failureMsg.toString());
262
+        } else {
263
+            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
264
+        }
265
+        return successMsg.toString();
266
+    }
267
+
268
+    /**
269
+     * 保存复审记录
270
+     * 
271
+     * @param certId 证书ID
272
+     * @param reviewRecords 复审记录列表
273
+     */
274
+    private void saveReviewRecords(Long certId, List<LedgerCertificateReviewRecord> reviewRecords) {
275
+        if (reviewRecords != null && !reviewRecords.isEmpty()) {
276
+            for (int i = 0; i < reviewRecords.size(); i++) {
277
+                LedgerCertificateReviewRecord record = reviewRecords.get(i);
278
+                record.setCertId(certId);
279
+                record.setReviewSeq(i + 1); // 设置复审次序
280
+                record.setCreateTime(DateUtils.getNowDate());
281
+                ledgerCertificateReviewRecordMapper.insertCertificateReviewRecord(record);
282
+            }
283
+        }
284
+    }
285
+
286
+    /**
287
+     * 同步更新用户表的证书等级
288
+     * 等级规则: 5<4<3<2<1 (数字越小等级越高)
289
+     * 如果出现更高等级,就更新用户表
290
+     * 
291
+     * @param userId 用户ID
292
+     * @param newCertLevel 新证书等级
293
+     */
294
+    private void syncUserQualificationLevel(Long userId, String newCertLevel) {
295
+        if (userId == null || newCertLevel == null || newCertLevel.trim().isEmpty()) {
296
+            return;
297
+        }
298
+        
299
+        try {
300
+            // 查询用户当前资质等级
301
+            SysUser user = sysUserService.selectUserById(userId);
302
+            if (user == null) {
303
+                return;
304
+            }
305
+            
306
+            String currentLevel = user.getQualificationLevel();
307
+            
308
+            // 如果用户当前没有等级,直接设置
309
+            if (currentLevel == null || currentLevel.trim().isEmpty()) {
310
+                updateUserQualificationLevel(userId, newCertLevel);
311
+                return;
312
+            }
313
+            
314
+            // 比较等级高低(数字越小等级越高)
315
+            int currentLevelNum = parseLevelToNumber(currentLevel);
316
+            int newLevelNum = parseLevelToNumber(newCertLevel);
317
+            
318
+            // 如果新等级更高,则更新用户表
319
+            if (newLevelNum < currentLevelNum) {
320
+                updateUserQualificationLevel(userId, newCertLevel);
321
+            }
322
+        } catch (Exception e) {
323
+            e.printStackTrace();
324
+        }
325
+    }
326
+    
327
+    /**
328
+     * 将等级字符串转换为数字进行比较
329
+     * 支持格式: "一级"、"LEVEL_ONE"、"1" 等
330
+     * 
331
+     * @param level 等级字符串
332
+     * @return 等级数字,无法解析返回 Integer.MAX_VALUE
333
+     */
334
+    private int parseLevelToNumber(String level) {
335
+        if (level == null || level.trim().isEmpty()) {
336
+            return Integer.MAX_VALUE;
337
+        }
338
+        
339
+        level = level.trim();
340
+        
341
+        // 中文等级
342
+        if (level.contains("一") || level.equals("1")) return 1;
343
+        if (level.contains("二") || level.equals("2")) return 2;
344
+        if (level.contains("三") || level.equals("3")) return 3;
345
+        if (level.contains("四") || level.equals("4")) return 4;
346
+        if (level.contains("五") || level.equals("5")) return 5;
347
+        
348
+        // 英文等级
349
+        if (level.toUpperCase().contains("ONE")) return 1;
350
+        if (level.toUpperCase().contains("TWO")) return 2;
351
+        if (level.toUpperCase().contains("THREE")) return 3;
352
+        if (level.toUpperCase().contains("FOUR")) return 4;
353
+        if (level.toUpperCase().contains("FIVE")) return 5;
354
+        
355
+        // 尝试直接解析为数字
356
+        try {
357
+            int num = Integer.parseInt(level);
358
+            return num >= 1 && num <= 5 ? num : Integer.MAX_VALUE;
359
+        } catch (NumberFormatException e) {
360
+            return Integer.MAX_VALUE;
361
+        }
362
+    }
363
+    
364
+    /**
365
+     * 更新用户的资质等级
366
+     * 
367
+     * @param userId 用户ID
368
+     * @param qualificationLevel 资质等级
369
+     */
370
+    private void updateUserQualificationLevel(Long userId, String qualificationLevel) {
371
+        try {
372
+            SysUser user = new SysUser();
373
+            user.setUserId(userId);
374
+            user.setQualificationLevel(qualificationLevel);
375
+            sysUserService.updateUserProfile(user);
376
+        } catch (Exception e) {
377
+            e.printStackTrace();
378
+        }
379
+    }
380
+}

+ 111 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/impl/LedgerLedgerCertificateReviewRecordServiceImpl.java

@@ -0,0 +1,111 @@
1
+package com.sundot.airport.ledger.service.impl;
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.utils.DateUtils;
7
+import com.sundot.airport.ledger.mapper.LedgerCertificateReviewRecordMapper;
8
+import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
9
+import com.sundot.airport.ledger.service.ILedgerCertificateReviewRecordService;
10
+
11
+/**
12
+ * 证书复审记录Service业务层处理
13
+ * 
14
+ * @author ruoyi
15
+ * @date 2026-06-29
16
+ */
17
+@Service
18
+public class LedgerLedgerCertificateReviewRecordServiceImpl implements ILedgerCertificateReviewRecordService {
19
+    @Autowired
20
+    private LedgerCertificateReviewRecordMapper ledgerCertificateReviewRecordMapper;
21
+
22
+    /**
23
+     * 查询证书复审记录
24
+     * 
25
+     * @param id 证书复审记录主键
26
+     * @return 证书复审记录
27
+     */
28
+    @Override
29
+    public LedgerCertificateReviewRecord selectCertificateReviewRecordById(Long id) {
30
+        return ledgerCertificateReviewRecordMapper.selectCertificateReviewRecordById(id);
31
+    }
32
+
33
+    /**
34
+     * 查询证书复审记录列表
35
+     * 
36
+     * @param ledgerCertificateReviewRecord 证书复审记录
37
+     * @return 证书复审记录
38
+     */
39
+    @Override
40
+    public List<LedgerCertificateReviewRecord> selectCertificateReviewRecordList(LedgerCertificateReviewRecord ledgerCertificateReviewRecord) {
41
+        return ledgerCertificateReviewRecordMapper.selectCertificateReviewRecordList(ledgerCertificateReviewRecord);
42
+    }
43
+
44
+    /**
45
+     * 根据证书ID查询复审记录列表
46
+     * 
47
+     * @param certId 证书ID
48
+     * @return 证书复审记录集合
49
+     */
50
+    @Override
51
+    public List<LedgerCertificateReviewRecord> selectCertificateReviewRecordByCertId(Long certId) {
52
+        return ledgerCertificateReviewRecordMapper.selectCertificateReviewRecordByCertId(certId);
53
+    }
54
+
55
+    /**
56
+     * 新增证书复审记录
57
+     * 
58
+     * @param ledgerCertificateReviewRecord 证书复审记录
59
+     * @return 结果
60
+     */
61
+    @Override
62
+    public int insertCertificateReviewRecord(LedgerCertificateReviewRecord ledgerCertificateReviewRecord) {
63
+        ledgerCertificateReviewRecord.setCreateTime(DateUtils.getNowDate());
64
+        return ledgerCertificateReviewRecordMapper.insertCertificateReviewRecord(ledgerCertificateReviewRecord);
65
+    }
66
+
67
+    /**
68
+     * 修改证书复审记录
69
+     * 
70
+     * @param ledgerCertificateReviewRecord 证书复审记录
71
+     * @return 结果
72
+     */
73
+    @Override
74
+    public int updateCertificateReviewRecord(LedgerCertificateReviewRecord ledgerCertificateReviewRecord) {
75
+        ledgerCertificateReviewRecord.setUpdateTime(DateUtils.getNowDate());
76
+        return ledgerCertificateReviewRecordMapper.updateCertificateReviewRecord(ledgerCertificateReviewRecord);
77
+    }
78
+
79
+    /**
80
+     * 批量删除证书复审记录
81
+     * 
82
+     * @param ids 需要删除的证书复审记录主键
83
+     * @return 结果
84
+     */
85
+    @Override
86
+    public int deleteCertificateReviewRecordByIds(Long[] ids) {
87
+        return ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByIds(ids);
88
+    }
89
+
90
+    /**
91
+     * 删除证书复审记录信息
92
+     * 
93
+     * @param id 证书复审记录主键
94
+     * @return 结果
95
+     */
96
+    @Override
97
+    public int deleteCertificateReviewRecordById(Long id) {
98
+        return ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordById(id);
99
+    }
100
+
101
+    /**
102
+     * 根据证书ID删除所有复审记录
103
+     * 
104
+     * @param certId 证书ID
105
+     * @return 结果
106
+     */
107
+    @Override
108
+    public int deleteCertificateReviewRecordByCertId(Long certId) {
109
+        return ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(certId);
110
+    }
111
+}

+ 304 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/utils/CertificateExcelImportUtil.java

@@ -0,0 +1,304 @@
1
+package com.sundot.airport.ledger.utils;
2
+
3
+import java.util.ArrayList;
4
+import java.util.Date;
5
+import java.util.HashMap;
6
+import java.util.List;
7
+import java.util.Map;
8
+import java.util.regex.Matcher;
9
+import java.util.regex.Pattern;
10
+
11
+import com.sundot.airport.common.utils.poi.ExcelUtil;
12
+import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
13
+import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
14
+import org.apache.poi.ss.usermodel.*;
15
+
16
+/**
17
+ * 证书Excel导入工具类
18
+ * 利用现有的ExcelUtil和@Excel注解实现动态列识别
19
+ * 
20
+ * @author ruoyi
21
+ * @date 2026-06-29
22
+ */
23
+public class CertificateExcelImportUtil {
24
+    
25
+    // 匹配格式: "第N次复审时间" 或 "第一次复审时间"
26
+    // 支持阿拉伯数字(1,2,3...999)和中文数字(一,二,三...九百九十九)
27
+    private static final Pattern REVIEW_TIME_PATTERN = Pattern.compile("第([\\d]+|[一二三四五六七八九十百千]+)次复审时间");
28
+    
29
+    /**
30
+     * 解析Excel文件,提取证书信息和复审记录
31
+     * 使用现有的ExcelUtil进行基本字段解析,额外处理动态的复审时间列
32
+     * 
33
+     * @param workbook Excel工作簿
34
+     * @return 证书信息列表(包含复审记录)
35
+     */
36
+    public static List<LedgerCertificateInfo> parseCertificateExcel(Workbook workbook) {
37
+        try {
38
+            // 将Workbook转换为InputStream以便重用ExcelUtil
39
+            // 注意:这里我们需要重新从workbook获取输入流,所以采用另一种方式
40
+            // 直接使用ExcelUtil,但它不支持动态列,所以我们需要扩展
41
+            
42
+            Sheet sheet = workbook.getSheetAt(0);
43
+            if (sheet == null) {
44
+                return new ArrayList<>();
45
+            }
46
+            
47
+            // 第一步:使用ExcelUtil解析基本字段(利用@Excel注解)
48
+            // 由于ExcelUtil需要InputStream,我们创建一个临时的
49
+            java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
50
+            workbook.write(baos);
51
+            java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(baos.toByteArray());
52
+            
53
+            ExcelUtil<LedgerCertificateInfo> excelUtil = new ExcelUtil<>(LedgerCertificateInfo.class);
54
+            List<LedgerCertificateInfo> certificateList = excelUtil.importExcel(bais, 0);
55
+            bais.close();
56
+            
57
+            // 第二步:解析复审时间列(动态列,不在@Excel注解中)
58
+            parseReviewTimeColumns(sheet, certificateList);
59
+            
60
+            return certificateList;
61
+            
62
+        } catch (Exception e) {
63
+            System.err.println("解析Excel失败: " + e.getMessage());
64
+            e.printStackTrace();
65
+            return new ArrayList<>();
66
+        }
67
+    }
68
+    
69
+    /**
70
+     * 解析复审时间列(动态列)
71
+     * 
72
+     * @param sheet Excel工作表
73
+     * @param certificateList 已解析的证书列表
74
+     */
75
+    private static void parseReviewTimeColumns(Sheet sheet, List<LedgerCertificateInfo> certificateList) {
76
+        if (certificateList == null || certificateList.isEmpty()) {
77
+            return;
78
+        }
79
+        
80
+        // 读取表头,找到所有"第N次复审时间"列的位置
81
+        Row headerRow = sheet.getRow(0);
82
+        if (headerRow == null) {
83
+            return;
84
+        }
85
+        
86
+        // 建立复审时间列映射: key=复审次序, value=列索引
87
+        Map<Integer, Integer> reviewTimeColumns = new HashMap<>();
88
+        for (int i = 0; i < headerRow.getLastCellNum(); i++) {
89
+            Cell cell = headerRow.getCell(i);
90
+            if (cell != null) {
91
+                String columnName = getCellValue(cell);
92
+                if (columnName != null) {
93
+                    // 去除所有空白字符(包括换行符\n、制表符\t、空格等)
94
+                    String cleanColumnName = columnName.replaceAll("\\s+", "");
95
+                    Matcher matcher = REVIEW_TIME_PATTERN.matcher(cleanColumnName);
96
+                    if (matcher.find()) {
97
+                        int seq = chineseToNumber(matcher.group(1));
98
+                        reviewTimeColumns.put(seq, i);
99
+                    }
100
+                }
101
+            }
102
+        }
103
+        
104
+        // 如果没有复审时间列,直接返回
105
+        if (reviewTimeColumns.isEmpty()) {
106
+            return;
107
+        }
108
+        
109
+        // 为每个证书提取复审记录
110
+        for (int i = 0; i < certificateList.size(); i++) {
111
+            LedgerCertificateInfo cert = certificateList.get(i);
112
+            // ExcelUtil已经从第1行开始读取数据,所以这里是 i+1
113
+            Row dataRow = sheet.getRow(i + 1);
114
+            if (dataRow == null) {
115
+                continue;
116
+            }
117
+            
118
+            List<LedgerCertificateReviewRecord> reviewRecords = new ArrayList<>();
119
+            for (Map.Entry<Integer, Integer> entry : reviewTimeColumns.entrySet()) {
120
+                int seq = entry.getKey();
121
+                int colIndex = entry.getValue();
122
+                
123
+                Cell cell = dataRow.getCell(colIndex);
124
+                Date reviewTime = parseDate(cell);
125
+                
126
+                if (reviewTime != null) {
127
+                    LedgerCertificateReviewRecord record = new LedgerCertificateReviewRecord();
128
+                    record.setReviewSeq(seq);
129
+                    record.setReviewTime(reviewTime);
130
+                    reviewRecords.add(record);
131
+                }
132
+            }
133
+            
134
+            cert.setReviewRecords(reviewRecords);
135
+        }
136
+    }
137
+    
138
+    /**
139
+     * 获取单元格值(复用ExcelUtil的逻辑)
140
+     */
141
+    private static String getCellValue(Cell cell) {
142
+        if (cell == null) {
143
+            return null;
144
+        }
145
+        
146
+        try {
147
+            switch (cell.getCellType()) {
148
+                case STRING:
149
+                    return cell.getStringCellValue().trim();
150
+                case NUMERIC:
151
+                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
152
+                        // 日期类型格式化为 yyyy-MM-dd
153
+                        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
154
+                        return sdf.format(cell.getDateCellValue());
155
+                    } else {
156
+                        double value = cell.getNumericCellValue();
157
+                        if (value == Math.floor(value)) {
158
+                            return String.valueOf((long) value);
159
+                        } else {
160
+                            return String.valueOf(value);
161
+                        }
162
+                    }
163
+                case BOOLEAN:
164
+                    return String.valueOf(cell.getBooleanCellValue());
165
+                case FORMULA:
166
+                    try {
167
+                        // 尝试获取数值结果
168
+                        return String.valueOf(cell.getNumericCellValue());
169
+                    } catch (Exception e) {
170
+                        // 如果失败,尝试获取字符串结果
171
+                        try {
172
+                            return cell.getStringCellValue().trim();
173
+                        } catch (Exception ex) {
174
+                            return cell.getCellFormula();
175
+                        }
176
+                    }
177
+                case BLANK:
178
+                    return "";
179
+                default:
180
+                    return null;
181
+            }
182
+        } catch (IllegalStateException e) {
183
+            // 处理类型不匹配的情况:尝试以字符串方式读取
184
+            try {
185
+                return cell.getStringCellValue().trim();
186
+            } catch (Exception ex) {
187
+                // 如果还是失败,返回null
188
+                return null;
189
+            }
190
+        } catch (Exception e) {
191
+            // 其他异常也返回null
192
+            return null;
193
+        }
194
+    }
195
+    
196
+    /**
197
+     * 解析日期
198
+     */
199
+    private static Date parseDate(Cell cell) {
200
+        if (cell == null) {
201
+            return null;
202
+        }
203
+        
204
+        // 如果是日期格式的单元格,直接返回 Date 对象
205
+        try {
206
+            if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
207
+                return cell.getDateCellValue();
208
+            }
209
+        } catch (Exception e) {
210
+            throw new RuntimeException("日期格式错误,e:", e);
211
+        }
212
+
213
+        
214
+        String value = getCellValue(cell);
215
+        if (value == null || value.isEmpty()) {
216
+            return null;
217
+        }
218
+        
219
+        // 尝试解析常见日期格式
220
+        String[] patterns = {
221
+            "yyyy-MM-dd",
222
+            "yyyy/MM/dd",
223
+            "yyyy年MM月dd日",
224
+            "MM/dd/yyyy",
225
+            "MM-dd-yyyy",
226
+            "dd-MMM-yyyy",  // 01-十二月-2012
227
+            "dd/MMM/yyyy",  // 01/Dec/2012
228
+            "yyyy-MM-dd HH:mm:ss",
229
+            "yyyy/MM/dd HH:mm:ss"
230
+        };
231
+        
232
+        for (String pattern : patterns) {
233
+            try {
234
+                java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(pattern, java.util.Locale.CHINA);
235
+                sdf.setLenient(false); // 严格模式
236
+                return sdf.parse(value);
237
+            } catch (Exception e) {
238
+                // 继续尝试下一个格式
239
+            }
240
+        }
241
+
242
+        return null;
243
+    }
244
+    
245
+    /**
246
+     * 中文数字转阿拉伯数字
247
+     * 支持: 一~九, 十, 十一~九十九, 一百~九百九十九等
248
+     */
249
+    private static int chineseToNumber(String chinese) {
250
+        // 如果是阿拉伯数字,直接返回
251
+        try {
252
+            return Integer.parseInt(chinese);
253
+        } catch (NumberFormatException e) {
254
+            // 不是阿拉伯数字,继续处理中文数字
255
+        }
256
+        
257
+        // 简单映射(个位数)
258
+        Map<String, Integer> basicMap = new HashMap<>();
259
+        basicMap.put("一", 1);
260
+        basicMap.put("二", 2);
261
+        basicMap.put("三", 3);
262
+        basicMap.put("四", 4);
263
+        basicMap.put("五", 5);
264
+        basicMap.put("六", 6);
265
+        basicMap.put("七", 7);
266
+        basicMap.put("八", 8);
267
+        basicMap.put("九", 9);
268
+        basicMap.put("十", 10);
269
+        
270
+        // 如果是个位数或十,直接返回
271
+        if (basicMap.containsKey(chinese)) {
272
+            return basicMap.get(chinese);
273
+        }
274
+        
275
+        // 处理复合数字: 十一~十九
276
+        if (chinese.startsWith("十") && chinese.length() == 2) {
277
+            String secondChar = chinese.substring(1);
278
+            if (basicMap.containsKey(secondChar)) {
279
+                return 10 + basicMap.get(secondChar);
280
+            }
281
+        }
282
+        
283
+        // 处理: 二十~九十九
284
+        if (chinese.length() == 2 && chinese.endsWith("十")) {
285
+            String firstChar = chinese.substring(0, 1);
286
+            if (basicMap.containsKey(firstChar)) {
287
+                return basicMap.get(firstChar) * 10;
288
+            }
289
+        }
290
+        
291
+        // 处理: 二十一~九十九
292
+        if (chinese.length() == 3 && chinese.charAt(1) == '十') {
293
+            String firstChar = chinese.substring(0, 1);
294
+            String thirdChar = chinese.substring(2, 3);
295
+            if (basicMap.containsKey(firstChar) && basicMap.containsKey(thirdChar)) {
296
+                return basicMap.get(firstChar) * 10 + basicMap.get(thirdChar);
297
+            }
298
+        }
299
+        
300
+        // 如果不支持中文数字格式,返回0
301
+        System.err.println("不支持的中文数字格式: " + chinese + ", 请使用阿拉伯数字");
302
+        return 0;
303
+    }
304
+}

+ 188 - 0
airport-ledger/src/main/resources/mapper/personnel/LedgerCertificateInfoMapper.xml

@@ -0,0 +1,188 @@
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.ledger.mapper.LedgerCertificateInfoMapper">
6
+    
7
+    <resultMap type="LedgerCertificateInfo" id="CertificateInfoResult">
8
+        <id     property="id"              column="id"              />
9
+        <result property="tenantId"        column="tenant_id"       />
10
+        <result property="unitName"        column="unit_name"       />
11
+        <result property="userId"          column="user_id"         />
12
+        <result property="personName"      column="person_name"     />
13
+        <result property="gender"          column="gender"          />
14
+        <result property="birthDate"       column="birth_date"      />
15
+        <result property="idCard"          column="id_card"         />
16
+        <result property="certLevel"       column="cert_level"      />
17
+        <result property="issueDate"       column="issue_date"      />
18
+        <result property="certNo"          column="cert_no"         />
19
+        <result property="theoryScore"     column="theory_score"    />
20
+        <result property="practiceScore"   column="practice_score"  />
21
+        <result property="evalScore"       column="eval_score"      />
22
+        <result property="employmentType"  column="employment_type" />
23
+        <result property="serviceMonths"   column="service_months"  />
24
+        <result property="expiryDate"      column="expiry_date"     />
25
+        <result property="status"          column="status"          />
26
+        <result property="expireDays"      column="expire_days"     />
27
+        <result property="remark"          column="remark"          />
28
+        <result property="createBy"        column="create_by"       />
29
+        <result property="createTime"      column="create_time"     />
30
+        <result property="updateBy"        column="update_by"       />
31
+        <result property="updateTime"      column="update_time"     />
32
+        <result property="delFlag"         column="del_flag"        />
33
+    </resultMap>
34
+
35
+    <sql id="selectCertificateInfoVo">
36
+        select id, tenant_id, unit_name, user_id, person_name, gender, birth_date, id_card, 
37
+               cert_level, issue_date, cert_no, theory_score, practice_score, eval_score, 
38
+               employment_type, service_months, expiry_date, status, expire_days, remark,
39
+               create_by, create_time, update_by, update_time, del_flag
40
+        from ledger_certificate_info
41
+    </sql>
42
+
43
+    <select id="selectCertificateInfoList" parameterType="LedgerCertificateInfo" resultMap="CertificateInfoResult">
44
+        <include refid="selectCertificateInfoVo"/>
45
+        <where>  
46
+            del_flag = '0'
47
+            <if test="tenantId != null and tenantId != ''"> and tenant_id = #{tenantId}</if>
48
+            <if test="unitName != null and unitName != ''"> and unit_name like concat('%', #{unitName}, '%')</if>
49
+            <if test="personName != null and personName != ''"> and person_name like concat('%', #{personName}, '%')</if>
50
+            <if test="gender != null and gender != ''"> and gender = #{gender}</if>
51
+            <if test="idCard != null and idCard != ''"> and id_card = #{idCard}</if>
52
+            <if test="certLevel != null and certLevel != ''"> and cert_level = #{certLevel}</if>
53
+            <if test="certNo != null and certNo != ''"> and cert_no = #{certNo}</if>
54
+            <if test="employmentType != null and employmentType != ''"> and employment_type = #{employmentType}</if>
55
+            <if test="status != null and status != ''"> and status = #{status}</if>
56
+            <if test="params.beginBirthDate != null and params.beginBirthDate != ''">
57
+                and date_format(birth_date,'%Y%m%d') &gt;= date_format(#{params.beginBirthDate},'%Y%m%d')
58
+            </if>
59
+            <if test="params.endBirthDate != null and params.endBirthDate != ''">
60
+                and date_format(birth_date,'%Y%m%d') &lt;= date_format(#{params.endBirthDate},'%Y%m%d')
61
+            </if>
62
+            <if test="params.beginIssueDate != null and params.beginIssueDate != ''">
63
+                and date_format(issue_date,'%Y%m%d') &gt;= date_format(#{params.beginIssueDate},'%Y%m%d')
64
+            </if>
65
+            <if test="params.endIssueDate != null and params.endIssueDate != ''">
66
+                and date_format(issue_date,'%Y%m%d') &lt;= date_format(#{params.endIssueDate},'%Y%m%d')
67
+            </if>
68
+            <if test="params.beginExpiryDate != null and params.beginExpiryDate != ''">
69
+                and date_format(expiry_date,'%Y%m%d') &gt;= date_format(#{params.beginExpiryDate},'%Y%m%d')
70
+            </if>
71
+            <if test="params.endExpiryDate != null and params.endExpiryDate != ''">
72
+                and date_format(expiry_date,'%Y%m%d') &lt;= date_format(#{params.endExpiryDate},'%Y%m%d')
73
+            </if>
74
+        </where>
75
+        order by create_time desc
76
+    </select>
77
+    
78
+    <select id="selectCertificateInfoById" parameterType="Long" resultMap="CertificateInfoResult">
79
+        <include refid="selectCertificateInfoVo"/>
80
+        where id = #{id} and del_flag = '0'
81
+    </select>
82
+
83
+    <select id="selectCertificateInfoByIdCard" parameterType="String" resultMap="CertificateInfoResult">
84
+        <include refid="selectCertificateInfoVo"/>
85
+        where id_card = #{idCard} and del_flag = '0' limit 1
86
+    </select>
87
+
88
+    <select id="selectCertificateInfoByCertNo" parameterType="String" resultMap="CertificateInfoResult">
89
+        <include refid="selectCertificateInfoVo"/>
90
+        where cert_no = #{certNo} and del_flag = '0' limit 1
91
+    </select>
92
+
93
+    <select id="selectCertificateInfoByUserIdAndCertNo" resultMap="CertificateInfoResult">
94
+        <include refid="selectCertificateInfoVo"/>
95
+        where user_id = #{userId} and cert_no = #{certNo} and del_flag = '0' limit 1
96
+    </select>
97
+        
98
+    <insert id="insertCertificateInfo" parameterType="LedgerCertificateInfo" useGeneratedKeys="true" keyProperty="id">
99
+        insert into ledger_certificate_info
100
+        <trim prefix="(" suffix=")" suffixOverrides=",">
101
+            <if test="tenantId != null and tenantId != ''">tenant_id,</if>
102
+            <if test="unitName != null and unitName != ''">unit_name,</if>
103
+            <if test="userId != null">user_id,</if>
104
+            <if test="personName != null and personName != ''">person_name,</if>
105
+            <if test="gender != null and gender != ''">gender,</if>
106
+            <if test="birthDate != null">birth_date,</if>
107
+            <if test="idCard != null and idCard != ''">id_card,</if>
108
+            <if test="certLevel != null and certLevel != ''">cert_level,</if>
109
+            <if test="issueDate != null">issue_date,</if>
110
+            <if test="certNo != null and certNo != ''">cert_no,</if>
111
+            <if test="theoryScore != null">theory_score,</if>
112
+            <if test="practiceScore != null">practice_score,</if>
113
+            <if test="evalScore != null">eval_score,</if>
114
+            <if test="employmentType != null and employmentType != ''">employment_type,</if>
115
+            <if test="serviceMonths != null">service_months,</if>
116
+            <if test="expiryDate != null">expiry_date,</if>
117
+            <if test="status != null and status != ''">status,</if>
118
+            <if test="expireDays != null">expire_days,</if>
119
+            <if test="remark != null and remark != ''">remark,</if>
120
+            <if test="createBy != null and createBy != ''">create_by,</if>
121
+            create_time,
122
+            del_flag
123
+         </trim>
124
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
125
+            <if test="tenantId != null and tenantId != ''">#{tenantId},</if>
126
+            <if test="unitName != null and unitName != ''">#{unitName},</if>
127
+            <if test="userId != null">#{userId},</if>
128
+            <if test="personName != null and personName != ''">#{personName},</if>
129
+            <if test="gender != null and gender != ''">#{gender},</if>
130
+            <if test="birthDate != null">#{birthDate},</if>
131
+            <if test="idCard != null and idCard != ''">#{idCard},</if>
132
+            <if test="certLevel != null and certLevel != ''">#{certLevel},</if>
133
+            <if test="issueDate != null">#{issueDate},</if>
134
+            <if test="certNo != null and certNo != ''">#{certNo},</if>
135
+            <if test="theoryScore != null">#{theoryScore},</if>
136
+            <if test="practiceScore != null">#{practiceScore},</if>
137
+            <if test="evalScore != null">#{evalScore},</if>
138
+            <if test="employmentType != null and employmentType != ''">#{employmentType},</if>
139
+            <if test="serviceMonths != null">#{serviceMonths},</if>
140
+            <if test="expiryDate != null">#{expiryDate},</if>
141
+            <if test="status != null and status != ''">#{status},</if>
142
+            <if test="expireDays != null">#{expireDays},</if>
143
+            <if test="remark != null and remark != ''">#{remark},</if>
144
+            <if test="createBy != null and createBy != ''">#{createBy},</if>
145
+            sysdate(),
146
+            '0'
147
+         </trim>
148
+    </insert>
149
+
150
+    <update id="updateCertificateInfo" parameterType="LedgerCertificateInfo">
151
+        update ledger_certificate_info
152
+        <trim prefix="SET" suffixOverrides=",">
153
+            <if test="tenantId != null and tenantId != ''">tenant_id = #{tenantId},</if>
154
+            <if test="unitName != null and unitName != ''">unit_name = #{unitName},</if>
155
+            <if test="userId != null">user_id = #{userId},</if>
156
+            <if test="personName != null and personName != ''">person_name = #{personName},</if>
157
+            <if test="gender != null and gender != ''">gender = #{gender},</if>
158
+            <if test="birthDate != null">birth_date = #{birthDate},</if>
159
+            <if test="idCard != null and idCard != ''">id_card = #{idCard},</if>
160
+            <if test="certLevel != null and certLevel != ''">cert_level = #{certLevel},</if>
161
+            <if test="issueDate != null">issue_date = #{issueDate},</if>
162
+            <if test="certNo != null and certNo != ''">cert_no = #{certNo},</if>
163
+            <if test="theoryScore != null">theory_score = #{theoryScore},</if>
164
+            <if test="practiceScore != null">practice_score = #{practiceScore},</if>
165
+            <if test="evalScore != null">eval_score = #{evalScore},</if>
166
+            <if test="employmentType != null and employmentType != ''">employment_type = #{employmentType},</if>
167
+            <if test="serviceMonths != null">service_months = #{serviceMonths},</if>
168
+            <if test="expiryDate != null">expiry_date = #{expiryDate},</if>
169
+            <if test="status != null and status != ''">status = #{status},</if>
170
+            <if test="expireDays != null">expire_days = #{expireDays},</if>
171
+            <if test="remark != null and remark != ''">remark = #{remark},</if>
172
+            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
173
+            update_time = sysdate()
174
+        </trim>
175
+        where id = #{id}
176
+    </update>
177
+
178
+    <delete id="deleteCertificateInfoById" parameterType="Long">
179
+        update ledger_certificate_info set del_flag = '2' where id = #{id}
180
+    </delete>
181
+
182
+    <delete id="deleteCertificateInfoByIds" parameterType="Long">
183
+        update ledger_certificate_info set del_flag = '2' where id in
184
+        <foreach item="id" collection="array" open="(" separator="," close=")">
185
+            #{id}
186
+        </foreach>
187
+    </delete>
188
+</mapper>

+ 112 - 0
airport-ledger/src/main/resources/mapper/personnel/LedgerCertificateReviewRecordMapper.xml

@@ -0,0 +1,112 @@
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.ledger.mapper.LedgerCertificateReviewRecordMapper">
6
+    
7
+    <resultMap type="LedgerCertificateReviewRecord" id="CertificateReviewRecordResult">
8
+        <id     property="id"            column="id"              />
9
+        <result property="certId"        column="cert_id"         />
10
+        <result property="reviewSeq"     column="review_seq"      />
11
+        <result property="reviewTime"    column="review_time"     />
12
+        <result property="reviewResult"  column="review_result"   />
13
+        <result property="reviewer"      column="reviewer"        />
14
+        <result property="remark"        column="remark"          />
15
+        <result property="createBy"      column="create_by"       />
16
+        <result property="createTime"    column="create_time"     />
17
+        <result property="updateBy"      column="update_by"       />
18
+        <result property="updateTime"    column="update_time"     />
19
+        <result property="delFlag"       column="del_flag"        />
20
+    </resultMap>
21
+
22
+    <sql id="selectCertificateReviewRecordVo">
23
+        select id, cert_id, review_seq, review_time, review_result, reviewer, remark,
24
+               create_by, create_time, update_by, update_time, del_flag
25
+        from certificate_review_record
26
+    </sql>
27
+
28
+    <select id="selectCertificateReviewRecordList" parameterType="LedgerCertificateReviewRecord" resultMap="CertificateReviewRecordResult">
29
+        <include refid="selectCertificateReviewRecordVo"/>
30
+        <where>  
31
+            del_flag = '0'
32
+            <if test="certId != null"> and cert_id = #{certId}</if>
33
+            <if test="reviewSeq != null"> and review_seq = #{reviewSeq}</if>
34
+            <if test="reviewResult != null and reviewResult != ''"> and review_result = #{reviewResult}</if>
35
+            <if test="reviewer != null and reviewer != ''"> and reviewer like concat('%', #{reviewer}, '%')</if>
36
+            <if test="params.beginReviewTime != null and params.beginReviewTime != ''">
37
+                and date_format(review_time,'%Y%m%d') &gt;= date_format(#{params.beginReviewTime},'%Y%m%d')
38
+            </if>
39
+            <if test="params.endReviewTime != null and params.endReviewTime != ''">
40
+                and date_format(review_time,'%Y%m%d') &lt;= date_format(#{params.endReviewTime},'%Y%m%d')
41
+            </if>
42
+        </where>
43
+        order by cert_id asc, review_seq asc
44
+    </select>
45
+    
46
+    <select id="selectCertificateReviewRecordById" parameterType="Long" resultMap="CertificateReviewRecordResult">
47
+        <include refid="selectCertificateReviewRecordVo"/>
48
+        where id = #{id} and del_flag = '0'
49
+    </select>
50
+
51
+    <select id="selectCertificateReviewRecordByCertId" parameterType="Long" resultMap="CertificateReviewRecordResult">
52
+        <include refid="selectCertificateReviewRecordVo"/>
53
+        where cert_id = #{certId} and del_flag = '0'
54
+        order by review_seq asc
55
+    </select>
56
+        
57
+    <insert id="insertCertificateReviewRecord" parameterType="LedgerCertificateReviewRecord" useGeneratedKeys="true" keyProperty="id">
58
+        insert into certificate_review_record
59
+        <trim prefix="(" suffix=")" suffixOverrides=",">
60
+            <if test="certId != null">cert_id,</if>
61
+            <if test="reviewSeq != null">review_seq,</if>
62
+            <if test="reviewTime != null">review_time,</if>
63
+            <if test="reviewResult != null and reviewResult != ''">review_result,</if>
64
+            <if test="reviewer != null and reviewer != ''">reviewer,</if>
65
+            <if test="remark != null and remark != ''">remark,</if>
66
+            <if test="createBy != null and createBy != ''">create_by,</if>
67
+            create_time,
68
+            del_flag
69
+         </trim>
70
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
71
+            <if test="certId != null">#{certId},</if>
72
+            <if test="reviewSeq != null">#{reviewSeq},</if>
73
+            <if test="reviewTime != null">#{reviewTime},</if>
74
+            <if test="reviewResult != null and reviewResult != ''">#{reviewResult},</if>
75
+            <if test="reviewer != null and reviewer != ''">#{reviewer},</if>
76
+            <if test="remark != null and remark != ''">#{remark},</if>
77
+            <if test="createBy != null and createBy != ''">#{createBy},</if>
78
+            sysdate(),
79
+            '0'
80
+         </trim>
81
+    </insert>
82
+
83
+    <update id="updateCertificateReviewRecord" parameterType="LedgerCertificateReviewRecord">
84
+        update certificate_review_record
85
+        <trim prefix="SET" suffixOverrides=",">
86
+            <if test="certId != null">cert_id = #{certId},</if>
87
+            <if test="reviewSeq != null">review_seq = #{reviewSeq},</if>
88
+            <if test="reviewTime != null">review_time = #{reviewTime},</if>
89
+            <if test="reviewResult != null and reviewResult != ''">review_result = #{reviewResult},</if>
90
+            <if test="reviewer != null and reviewer != ''">reviewer = #{reviewer},</if>
91
+            <if test="remark != null and remark != ''">remark = #{remark},</if>
92
+            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
93
+            update_time = sysdate()
94
+        </trim>
95
+        where id = #{id}
96
+    </update>
97
+
98
+    <delete id="deleteCertificateReviewRecordById" parameterType="Long">
99
+        update certificate_review_record set del_flag = '2' where id = #{id}
100
+    </delete>
101
+
102
+    <delete id="deleteCertificateReviewRecordByIds" parameterType="Long">
103
+        update certificate_review_record set del_flag = '2' where id in
104
+        <foreach item="id" collection="array" open="(" separator="," close=")">
105
+            #{id}
106
+        </foreach>
107
+    </delete>
108
+
109
+    <delete id="deleteCertificateReviewRecordByCertId" parameterType="Long">
110
+        update certificate_review_record set del_flag = '2' where cert_id = #{certId}
111
+    </delete>
112
+</mapper>