diff --git a/gather-app/src/main/java/com/ruoyi/business/util/CompreFace.java b/gather-app/src/main/java/com/ruoyi/business/util/CompreFace.java new file mode 100644 index 0000000..8d0bc64 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/business/util/CompreFace.java @@ -0,0 +1,72 @@ +package com.ruoyi.business.util; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CompreFace { + + protected static final Logger logger = LoggerFactory.getLogger(CompreFace.class); + + private static final String FACE_VERIFY_URL = "http://50.146.63.165:8000/api/v1/verification/verify"; + + + + + public static JSONObject faceVerify(String source_image,String target_image){ + // 目标URL + String url = FACE_VERIFY_URL + "?face_plugins=landmarks&face_plugins=gender&face_plugins=age&face_plugins=pose"; + + StringBuilder jsonBuilder = new StringBuilder(); + jsonBuilder.append("{") + .append("\"source_image\": \"") + .append(source_image) + .append("\",\"target_image\": \"") + .append(target_image) + .append("\"}"); + String json = jsonBuilder.toString(); + +// logger.info("Sending request with JSON: {}", json); + + // 创建HttpClient实例 + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + // 创建HttpPost实例 + HttpPost httpPost = new HttpPost(url); + + // 设置请求头 + httpPost.setHeader("Content-Type", "application/json"); + httpPost.setHeader("x-api-key", "77997347-5c11-4e41-b290-e00c7c441b23"); + + // 创建StringEntity对象,将JSON字符串设置为请求体 + StringEntity entity = new StringEntity(json, "UTF-8"); + httpPost.setEntity(entity); + + // 发送请求并获取响应 + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + // 读取响应内容 + String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); + logger.info("Response: {}", responseString); + if (responseString != null){ + JSONObject jsonObject = new JSONObject(responseString); + JSONArray result = jsonObject.getJSONArray("result"); + if (result != null){ + JSONObject resultJSONObject = result.getJSONObject(0); + if (resultJSONObject != null){ + return resultJSONObject; + } + } + } + } + } catch (Exception e) { + logger.error("Error sending message", e); + } + return null; + } +} diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/BusinessTripApproval.java b/gather-app/src/main/java/com/ruoyi/database/domain/BusinessTripApproval.java new file mode 100644 index 0000000..390fa48 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/BusinessTripApproval.java @@ -0,0 +1,61 @@ +package com.ruoyi.database.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@TableName("business_trip_approval") +@ApiModel("出差审批单") +public class BusinessTripApproval { + + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("出差人员姓名") + private String name; + + @ApiModelProperty("部门") + private String department; + + @ApiModelProperty("出差事由") + private String reason; + + @ApiModelProperty("出差目的地") + private String destination; + + @ApiModelProperty("出差开始日期") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate startDate; + + @ApiModelProperty("出差结束日期") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate endDate; + + @ApiModelProperty("拟乘交通工具(飞机/火车/汽车/轮船/其他)") + private String transport; + + @ApiModelProperty("是否自带公务车辆(0-否 1-是)") + private Integer hasOfficialCar; + + @ApiModelProperty("单位负责人意见") + private String deptLeaderOpinion; + + @ApiModelProperty("局分管负责人意见") + private String LeaderOpinion; + + @ApiModelProperty("局主要领导意见") + private String mainLeaderOpinion; + + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/NonWorkingDayDrinkingReport.java b/gather-app/src/main/java/com/ruoyi/database/domain/NonWorkingDayDrinkingReport.java new file mode 100644 index 0000000..92629a5 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/NonWorkingDayDrinkingReport.java @@ -0,0 +1,73 @@ +package com.ruoyi.database.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +@Data +@TableName("non_working_day_drinking_report") +@ApiModel("非工作日饮酒报备单") +public class NonWorkingDayDrinkingReport { + + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("姓名") + private String name; + + @ApiModelProperty("单位职务") + private String position; + + @ApiModelProperty("饮酒时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime drinkTime; + + @ApiModelProperty("出行方式") + private String travelMode; + + @ApiModelProperty("饮酒地点") + private String drinkPlace; + + @ApiModelProperty("饮酒事由") + private String reason; + + @ApiModelProperty("是否本人付款(0-否 1-是)") + private Integer isSelfPay; + + @ApiModelProperty("是否有管理和服务对象参与(0-否 1-是)") + private Integer hasServiceObject; + + @ApiModelProperty("是否参与影响公正执行公务的宴请(0-否 1-是)") + private Integer affectOfficialDuties; + + @ApiModelProperty("是否存在领导干部/单位间相互宴请(0-否 1-是)") + private Integer mutualBanquet; + + @ApiModelProperty("是否接受下属或地方公安机关宴请(0-否 1-是)") + private Integer acceptSubordinateInvite; + + @ApiModelProperty("是否出入私人会所或参与一桌餐(0-否 1-是)") + private Integer privateClub; + + @ApiModelProperty("备注说明") + private String remark; + + @ApiModelProperty("承诺人签名") + private String commitmentSign; + + @ApiModelProperty("责任领导签名") + private String leaderSign; + + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/PoliceBusinessReport.java b/gather-app/src/main/java/com/ruoyi/database/domain/PoliceBusinessReport.java new file mode 100644 index 0000000..b195691 --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/PoliceBusinessReport.java @@ -0,0 +1,65 @@ +package com.ruoyi.database.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@TableName("police_business_report") +@ApiModel("民警出差/学习培训/请销假/抽调报备表") +public class PoliceBusinessReport { + + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("姓名") + private String name; + + @ApiModelProperty("身份证号码") + private String idCard; + + @ApiModelProperty("参加工作时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate joinWorkTime; + + @ApiModelProperty("联系电话") + private String phone; + + @ApiModelProperty("所在部门") + private String department; + + @ApiModelProperty("外出原因(出差/学习培训/请销假/抽调)") + private String reason; + + @ApiModelProperty("开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime startTime; + + @ApiModelProperty("结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime endTime; + + @ApiModelProperty("所在单位意见") + private String deptOpinion; + + @ApiModelProperty("局领导意见") + private String leaderOpinion; + + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @ApiModelProperty("创建人") + private String createBy; +} \ No newline at end of file diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/PoliceLeaveApproval.java b/gather-app/src/main/java/com/ruoyi/database/domain/PoliceLeaveApproval.java new file mode 100644 index 0000000..1d4547d --- /dev/null +++ b/gather-app/src/main/java/com/ruoyi/database/domain/PoliceLeaveApproval.java @@ -0,0 +1,68 @@ +package com.ruoyi.database.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@TableName("police_leave_approval") +@ApiModel("民警请(休)假审批表") +public class PoliceLeaveApproval { + + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("姓名") + private String name; + + @ApiModelProperty("身份证号码") + private String idCard; + + @ApiModelProperty("参加工作时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate joinWorkTime; + + @ApiModelProperty("联系电话") + private String phone; + + @ApiModelProperty("所在单位") + private String deptName; + + @ApiModelProperty("请假事由(1-公休假 2-事假 3-探亲假 4-婚假 5-产假 6-护理假 7-病假 8-育儿假 9-其他)") + private Integer leaveType; + + @ApiModelProperty("请假开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime startDate; + + @ApiModelProperty("请假结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime endDate; + + @ApiModelProperty("所在单位意见") + private String deptOpinion; + + @ApiModelProperty("政治处意见") + private String politicalOpinion; + + @ApiModelProperty("局领导审批意见") + private String leaderApproval; + + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @ApiModelProperty("创建人") + private String createBy; +} \ No newline at end of file diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRequest.java b/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRequest.java index e462ba0..cbcbb8a 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRequest.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/VehicleRequest.java @@ -26,6 +26,9 @@ public class VehicleRequest { @ApiModelProperty("申请人姓名") private String appName; + @ApiModelProperty("行驶里程") + private String drivingMileage; + @ApiModelProperty("申请人警号") private String badgeNumber; @@ -91,14 +94,17 @@ public class VehicleRequest { @ApiModelProperty("文件编号") private String fileCode; - @ApiModelProperty("随行人员姓名") + @ApiModelProperty("乘车人员姓名") private String entourage; - @ApiModelProperty("随行人员警号") - private String entourageBadgeNumber; + @ApiModelProperty("乘车人员数量") + private Integer entourageNumber; - @ApiModelProperty("随行人员职务") - private String entourageDuty; + @ApiModelProperty("报销人员姓名") + private String entourage2; + + @ApiModelProperty("报销人员数量") + private Integer entourageNumber2; @ApiModelProperty("审批流程 0-未审批 1-部门审批通过 2-部门审批不通过 3-警务保障部门审批通过 4-警务保障部门审批不通过 5-局领导审批通过 6-局领导审批不通过") private Integer state; diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index 3244c3c..e20a8d7 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -1,7 +1,9 @@ package com.ruoyi.web.controller.system; +import cn.hutool.json.JSONArray; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.ruoyi.business.util.CompreFace; import com.alibaba.fastjson.parser.Feature; import com.ruoyi.business.util.StringKit; import com.ruoyi.cache.SmsCache; @@ -27,6 +29,14 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; /** @@ -119,6 +129,53 @@ public class SysLoginController { } + @ApiOperation("人脸识别登录") + @PostMapping("/loginByFace") + public AjaxResult faceLogin(MultipartFile imgName) { + try { + if (imgName != null) { + Path filePath = Paths.get(PATH_PREFIX, imgName.getOriginalFilename()); + File dest = new File(filePath.toString()); + // 确保目标目录存在 + Files.createDirectories(dest.getParentFile().toPath()); + // 保存文件到指定路径 + imgName.transferTo(dest); + List imageFiles = getImagesFromDirectory(USER_PATH_PREFIX); + for (String imageFile : imageFiles) { + cn.hutool.json.JSONObject jsonObject = CompreFace.faceVerify(convertPngToBase64(imageFile), convertPngToBase64(PATH_PREFIX + dest.getName())); + if (jsonObject != null){ + JSONArray face_matches = jsonObject.getJSONArray("face_matches"); + System.out.println("图片中出现" + face_matches.size() + "张人脸"); + for (int i = 0; i < face_matches.size(); i++) { + cn.hutool.json.JSONObject matchesJSONObject = face_matches.getJSONObject(i); + Double similarity = matchesJSONObject.getDouble("similarity"); + System.out.println("人脸相似度:" + similarity); + if (similarity >= 0.995){ + System.out.println("人脸识别通过"); + String substring = imageFile.substring(imageFile.lastIndexOf("/") + 1, imageFile.lastIndexOf(".")); + System.out.println("识别用户为" + substring); + AjaxResult ajax = AjaxResult.success(); + String token = loginService.loginAppBySms(substring, substring); + JSONObject resJson = new JSONObject(); + resJson.put(Constants.TOKEN, token); + resJson.put("user", substring); + ajax.put(Constants.TOKEN, resJson); + return ajax; + } + } + } + } + System.out.println("人脸不匹配"); + return AjaxResult.error("人脸识别不通过,请靠近摄像头或拿掉面部遮挡物"); + } else { + return AjaxResult.error("没图片"); + } + } catch (Exception e) { +// logger.info(StringKit.getTrace(e)); + return AjaxResult.error("系统错误,请联系管理员"); + } + } + @ApiOperation("短信验证码登录") @PostMapping("/loginBySMS") public AjaxResult loginBySMS(@RequestBody SMSLoginDto smsLoginDto) { @@ -260,4 +317,66 @@ public class SysLoginController { List menus = menuService.selectMenuTreeByUserId(userId); return AjaxResult.success(menuService.buildMenus(menus)); } + + + public static List getImagesFromDirectory(String directoryPath) { + List imageFiles = new ArrayList<>(); + File directory = new File(directoryPath); + + // Check if the specified path is a directory + if (!directory.exists() || !directory.isDirectory()) { + System.out.println("The specified path is not a directory or does not exist."); + return imageFiles; + } + + // Walk through the directory tree + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + // Recursively search subdirectories + imageFiles.addAll(getImagesFromDirectory(file.getAbsolutePath())); + } else { + // Check if the file is an image based on its extension + String fileName = file.getName(); + int dotIndex = fileName.lastIndexOf('.'); + if (dotIndex != -1) { + String extension = fileName.substring(dotIndex + 1).toLowerCase(); + if (IMAGE_EXTENSIONS.contains(extension)) { + imageFiles.add(file.getAbsolutePath()); + } + } + } + } + } + + return imageFiles; + } + + public static String convertPngToBase64(String filePath) { + File file = new File(filePath); + + // 检查文件是否存在 + if (!file.exists() || !file.isFile()) { + System.out.println("File not found: " + filePath); + return null; + } + + // 读取文件为字节数组 + byte[] fileContent = null; + try (FileInputStream fis = new FileInputStream(file)) { + fileContent = new byte[(int) file.length()]; + int bytesRead = fis.read(fileContent); + if (bytesRead != fileContent.length) { + throw new IOException("Could not read the entire file to the byte array."); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + // 将字节数组转换为Base64字符串 + String base64String = Base64.getEncoder().encodeToString(fileContent); + return base64String; + } } diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 28307a2..2502f93 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -18,7 +18,7 @@ ruoyi: # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 - port: 9898 + port: 8090 servlet: # 应用的访问路径 context-path: /PublicAffairs/