Преглед изворни кода

1、增加灯塔logo
2、人脸识别功能
3、bugfix

lihao16 пре 1 година
родитељ
комит
79523667a2
40 измењених фајлова са 558 додато и 106 уклоњено
  1. 1 1
      inspur-admin/src/main/java/com/inspur/InspurApplication.java
  2. 9 8
      inspur-admin/src/main/java/com/inspur/web/controller/partywork/PartyMeetingInfoController.java
  3. 10 0
      inspur-admin/src/main/java/com/inspur/web/controller/partywork/RemoteControlController.java
  4. 3 3
      inspur-admin/src/main/resources/application-druid.yml
  5. 0 5
      inspur-ai/pom.xml
  6. 34 0
      inspur-ai/src/main/java/com/inspur/face/common/FaceConstant.java
  7. 7 2
      inspur-ai/src/main/java/com/inspur/face/controller/CompreFaceController.java
  8. 2 0
      inspur-ai/src/main/java/com/inspur/face/domain/PartyFaceRecognition.java
  9. 17 0
      inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRsp.java
  10. 19 0
      inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRspResult.java
  11. 25 0
      inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRspResultBox.java
  12. 19 0
      inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRspResultSubject.java
  13. 3 1
      inspur-ai/src/main/java/com/inspur/face/service/CompreFaceService.java
  14. 71 49
      inspur-ai/src/main/java/com/inspur/face/service/impl/CompreFaceServiceImpl.java
  15. 7 1
      inspur-ai/src/main/resources/mapper/PartyFaceRecognitionMapper.xml
  16. 10 0
      inspur-party/src/main/java/com/inspur/mapper/PartyAttendanceRecordMapper.java
  17. 5 0
      inspur-party/src/main/java/com/inspur/service/partywork/IPartyMeetingInfoService.java
  18. 9 0
      inspur-party/src/main/java/com/inspur/service/partywork/IRemoteControlService.java
  19. 153 4
      inspur-party/src/main/java/com/inspur/service/partywork/impl/PartyMeetingInfoServiceImpl.java
  20. 13 6
      inspur-party/src/main/java/com/inspur/service/partywork/impl/RemoteControlServiceImpl.java
  21. 4 0
      inspur-party/src/main/resources/mapper/PartyAttendanceRecordMapper.xml
  22. 6 1
      inspur-pc/src/main/java/com/inspur/netty/message/push/PushMessageType.java
  23. 2 2
      inspur-ui/.env.development
  24. 4 4
      inspur-ui/.env.production
  25. 2 2
      inspur-ui/.env.staging
  26. 1 1
      inspur-ui/package.json
  27. BIN
      inspur-ui/public/favicon.ico
  28. BIN
      inspur-ui/public/favicon.ico_old
  29. 9 1
      inspur-ui/src/api/partywork/face.js
  30. 8 0
      inspur-ui/src/api/partywork/remoteControl.js
  31. BIN
      inspur-ui/src/assets/logo/dt_logo.png
  32. 5 5
      inspur-ui/src/layout/components/Navbar.vue
  33. 1 1
      inspur-ui/src/layout/components/Sidebar/Logo.vue
  34. 1 1
      inspur-ui/src/views/index.vue
  35. 2 2
      inspur-ui/src/views/login.vue
  36. 5 1
      inspur-ui/src/views/party_work/meeting/branch_party.vue
  37. 88 2
      inspur-ui/src/views/party_work/meeting/info.vue
  38. 1 1
      inspur-ui/src/views/register.vue
  39. 1 1
      inspur-ui/vue.config.js
  40. 1 1
      pom.xml

+ 1 - 1
inspur-admin/src/main/java/com/inspur/InspurApplication.java

@@ -16,7 +16,7 @@ public class InspurApplication
     {
         // System.setProperty("spring.devtools.restart.enabled", "false");
         SpringApplication.run(InspurApplication.class, args);
-        System.out.println(" ======  智慧党建管理系统   ======  \n" +
+        System.out.println(" ======  灯塔智慧党建管理系统   ======  \n" +
                 " ___  ________   ________  ________  ___  ___  ________     \n" +
                 "|\\  \\|\\   ___  \\|\\   ____\\|\\   __  \\|\\  \\|\\  \\|\\   __  \\    \n" +
                 "\\ \\  \\ \\  \\\\ \\  \\ \\  \\___|\\ \\  \\|\\  \\ \\  \\\\\\  \\ \\  \\|\\  \\   \n" +

+ 9 - 8
inspur-admin/src/main/java/com/inspur/web/controller/partywork/PartyMeetingInfoController.java

@@ -5,23 +5,18 @@ import javax.servlet.http.HttpServletResponse;
 
 import com.inspur.domain.app.PartyAppUser;
 import com.inspur.domain.partywork.PartyMeetingInfo;
+import com.inspur.face.service.CompreFaceService;
 import com.inspur.service.partywork.IPartyMeetingInfoService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import com.inspur.common.annotation.Log;
 import com.inspur.common.core.controller.BaseController;
 import com.inspur.common.core.domain.AjaxResult;
 import com.inspur.common.enums.BusinessType;
 import com.inspur.common.utils.poi.ExcelUtil;
 import com.inspur.common.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 党员会议Controller
@@ -36,6 +31,7 @@ public class PartyMeetingInfoController extends BaseController
     @Autowired
     private IPartyMeetingInfoService partyMeetingInfoService;
 
+
     /**
      * 查询党员会议列表
      */
@@ -175,4 +171,9 @@ public class PartyMeetingInfoController extends BaseController
             return AjaxResult.success(i);
         }
     }
+
+    @PostMapping("/face/sign")
+    public AjaxResult recognizeFace(@RequestParam("meetingId") Long meetingId, @RequestBody MultipartFile file) {
+        return partyMeetingInfoService.recognizeFace(meetingId,file);
+    }
 }

+ 10 - 0
inspur-admin/src/main/java/com/inspur/web/controller/partywork/RemoteControlController.java

@@ -2,12 +2,16 @@ package com.inspur.web.controller.partywork;
 
 import com.inspur.common.core.controller.BaseController;
 import com.inspur.common.core.domain.AjaxResult;
+import com.inspur.common.core.page.TableDataInfo;
+import com.inspur.face.domain.PartyFaceRecognition;
 import com.inspur.netty.message.push.UrlControl;
 import com.inspur.service.partywork.IRemoteControlService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.List;
+
 /**
  * 远程控制 controller
  * @author lihao16
@@ -51,6 +55,12 @@ public class RemoteControlController extends BaseController {
         return remoteControlService.takePhoto(meetingId,deviceId);
     }
 
+    @GetMapping("/takePhotoSign")
+    public AjaxResult takePhotoSign(@RequestParam("meetingId") Long meetingId, @RequestParam("deviceId")Long deviceId)
+    {
+        return remoteControlService.takePhotoSign(meetingId,deviceId);
+    }
+
     @PostMapping("/photo/upload")
     public AjaxResult photoUpload(@RequestParam Long meetingId,@RequestBody MultipartFile file)  {
         return remoteControlService.photoUpload(meetingId,file);

+ 3 - 3
inspur-admin/src/main/resources/application-druid.yml

@@ -6,10 +6,10 @@ spring:
         druid:
             # 主库数据源
             master:
-                # url: jdbc:mysql://117.73.3.135:3306/partybuild-admin-v1.4?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                url: jdbc:mysql://127.0.0.1:3306/partybuild-admin-v1.4?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                url: jdbc:mysql://117.73.3.135:3306/partybuild-admin-dt?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                # url: jdbc:mysql://127.0.0.1:3306/partybuild-admin-v1.4?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
-                password: password
+                password: Hycpb@123
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭

+ 0 - 5
inspur-ai/pom.xml

@@ -49,11 +49,6 @@
             <artifactId>chatgpt-java</artifactId>
             <version>1.1.5</version>
         </dependency>
-        <!--<dependency>
-            <groupId>com.squareup.okhttp3</groupId>
-            <artifactId>okhttp</artifactId>
-            <version>4.12.0</version>
-        </dependency>-->
     </dependencies>
 
 </project>

+ 34 - 0
inspur-ai/src/main/java/com/inspur/face/common/FaceConstant.java

@@ -0,0 +1,34 @@
+package com.inspur.face.common;
+
+
+/**
+ * 人脸识别常量
+ *
+ * @author lihao16
+ */
+public class FaceConstant {
+
+    /**
+     * 添加subject URL
+     */
+    public static final String URL_ADD_SUBJECT = "http://117.73.13.40:8000/api/v1/recognition/subjects";
+
+    /**
+     * 上传人脸照片 URL
+     */
+    public static final String URL_UPLOAD_FACE = "http://117.73.13.40:8000/api/v1/recognition/faces?subject=";
+
+    /**
+     * 人脸识别 URL
+     */
+    // public static final String URL_FACE_RECOGNITION = "http://117.73.13.40:8000/api/v1/recognition/recognize?face_plugins=landmarks&face_plugins=gender&face_plugins=age&face_plugins=pose";
+    public static final String URL_FACE_RECOGNITION = "http://117.73.13.40:8000/api/v1/recognition/recognize";
+
+    public final static String API_KEY = "fccde51d-9b32-4468-97b1-cf454b473e55";
+    // public final static String API_KEY = "f5c06ee0-3c3a-47f2-ae49-fb0b7d899f19";
+
+    public static final String FILE_TEMP_PATH = "/home/inspur/party-admin/temp/";
+
+    public static final String FACE_RECOGNITION_TABLE_NAME = "party_face_recognition";
+
+}

+ 7 - 2
inspur-ai/src/main/java/com/inspur/face/controller/CompreFaceController.java

@@ -48,8 +48,13 @@ public class CompreFaceController extends BaseController {
     }
 
     @PostMapping("/recognition/recognize")
-    public AjaxResult recognizeFace(@RequestBody MultipartFile file) {
-        return compreFaceService.recognizeFace(file);
+    public AjaxResult recognizeFace(@RequestParam("meetingId") Long meetingId, @RequestBody MultipartFile file) {
+        return compreFaceService.recognizeFace(meetingId,file);
+    }
+
+    @GetMapping("/recognition/signRecord")
+    public AjaxResult photoSignRecord(@RequestParam("meetingId") Long meetingId) {
+        return compreFaceService.photoSignRecord(meetingId);
     }
 
     @GetMapping("/record/{id}")

+ 2 - 0
inspur-ai/src/main/java/com/inspur/face/domain/PartyFaceRecognition.java

@@ -42,4 +42,6 @@ public class PartyFaceRecognition extends BaseEntity
 
     private Long memberId;
 
+    private Long meetingId;
+
 }

+ 17 - 0
inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRsp.java

@@ -0,0 +1,17 @@
+package com.inspur.face.domain;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 人脸识别模型算法API返回
+ *
+ * @author lihao16
+ */
+@Data
+public class RecognizeFaceRsp {
+
+    private List<RecognizeFaceRspResult> result;
+
+}

+ 19 - 0
inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRspResult.java

@@ -0,0 +1,19 @@
+package com.inspur.face.domain;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * AI人脸识别结果返回result
+ *
+ * @author lihao16
+ */
+@Data
+public class RecognizeFaceRspResult {
+
+    private RecognizeFaceRspResultBox box;
+
+    private List<RecognizeFaceRspResultSubject> subjects;
+
+}

+ 25 - 0
inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRspResultBox.java

@@ -0,0 +1,25 @@
+package com.inspur.face.domain;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * AI人脸识别结果返回box
+ *
+ * @author lihao16
+ */
+@Data
+public class RecognizeFaceRspResultBox {
+
+    private BigDecimal probability;
+
+    private Integer x_max;
+
+    private Integer y_max;
+
+    private Integer x_min;
+
+    private Integer y_min;
+
+}

+ 19 - 0
inspur-ai/src/main/java/com/inspur/face/domain/RecognizeFaceRspResultSubject.java

@@ -0,0 +1,19 @@
+package com.inspur.face.domain;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * AI人脸识别结果返回subject
+ *
+ * @author lihao16
+ */
+@Data
+public class RecognizeFaceRspResultSubject {
+
+    private String subject;
+
+    private BigDecimal similarity;
+
+}

+ 3 - 1
inspur-ai/src/main/java/com/inspur/face/service/CompreFaceService.java

@@ -20,7 +20,7 @@ public interface CompreFaceService {
 
     public AjaxResult uploadFace(String subject, MultipartFile file);
 
-    public AjaxResult recognizeFace(MultipartFile file);
+    public AjaxResult recognizeFace(Long meetingId,MultipartFile file);
 
     public AjaxResult recordInfo(Long id);
 
@@ -29,4 +29,6 @@ public interface CompreFaceService {
     public AjaxResult uploadFace2(PartyMemberFace partyMemberFace);
 
     public List<PartyFaceRecognition> selectPartyFaceRecognitionList(PartyFaceRecognition partyFaceRecognition);
+
+    public AjaxResult photoSignRecord(Long meetingId);
 }

+ 71 - 49
inspur-ai/src/main/java/com/inspur/face/service/impl/CompreFaceServiceImpl.java

@@ -14,9 +14,8 @@ import com.inspur.common.utils.SecurityUtils;
 import com.inspur.common.utils.StringUtils;
 import com.inspur.common.utils.file.FileUploadUtils;
 import com.inspur.common.utils.file.FileUtils;
-import com.inspur.face.domain.PartyFaceRecognition;
-import com.inspur.face.domain.PartyMemberFace;
-import com.inspur.face.domain.SubjectBean;
+import com.inspur.face.common.FaceConstant;
+import com.inspur.face.domain.*;
 import com.inspur.face.mapper.PartyFaceRecognitionMapper;
 import com.inspur.face.service.CompreFaceService;
 import com.inspur.framework.config.ServerConfig;
@@ -31,10 +30,8 @@ import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import java.math.BigDecimal;
+import java.util.*;
 
 import static com.inspur.common.utils.PageUtils.startPage;
 
@@ -57,35 +54,25 @@ public class CompreFaceServiceImpl implements CompreFaceService {
     @Autowired
     private ISysUserTableRelService sysUserTableRelService;
 
-    private static final String FACE_RECOGNITION_TABLE_NAME = "party_face_recognition";
 
     private final static String MEMBER_TABLE_NAME = "party_member_manage";
 
-    /**
-     * 添加subject URL
-     */
-    public static final String URL_ADD_SUBJECT = "http://117.73.13.40:8000/api/v1/recognition/subjects";
-
-    /**
-     * 上传人脸照片 URL
-     */
-    public static final String URL_UPLOAD_FACE = "http://117.73.13.40:8000/api/v1/recognition/faces?subject=";
-
-    /**
-     * 人脸识别 URL
-     */
-    // public static final String URL_FACE_RECOGNITION = "http://117.73.13.40:8000/api/v1/recognition/recognize?face_plugins=landmarks&face_plugins=gender&face_plugins=age&face_plugins=pose";
-    public static final String URL_FACE_RECOGNITION = "http://117.73.13.40:8000/api/v1/recognition/recognize";
-
-    private final static String API_KEY = "fccde51d-9b32-4468-97b1-cf454b473e55";
-
-    private static final String FILE_TEMP_PATH = "/home/inspur/party-admin/temp/";
-
+    @Override
+    public AjaxResult photoSignRecord(Long meetingId) {
+        PartyFaceRecognition queryParam = new PartyFaceRecognition();
+        queryParam.setMeetingId(meetingId);
+        queryParam.setOpType(3);
+        List<PartyFaceRecognition> partyFaceRecognitionList = partyFaceRecognitionMapper.selectPartyFaceRecognitionList(queryParam);
+        if (CollectionUtils.isEmpty(partyFaceRecognitionList)) {
+            return AjaxResult.error("未找到会议签到记录");
+        }
+        return AjaxResult.success(partyFaceRecognitionList.get(0));
+    }
 
     @Override
     public List<PartyFaceRecognition> selectPartyFaceRecognitionList(PartyFaceRecognition partyFaceRecognition) {
         Long userId = SecurityUtils.getLoginUser().getUserId();
-        partyFaceRecognition.setUserTableId(getUserTableId(FACE_RECOGNITION_TABLE_NAME, userId, 0));
+        partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
         startPage();
         return partyFaceRecognitionMapper.selectPartyFaceRecognitionList(partyFaceRecognition);
     }
@@ -99,7 +86,7 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         partyFaceRecognition.setOpType(1);
         partyFaceRecognition.setOpStatus(0);
         partyFaceRecognition.setCreateTime(DateUtils.getNowDate());
-        partyFaceRecognition.setUserTableId(getUserTableId(FACE_RECOGNITION_TABLE_NAME, userId, 0));
+        partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
         partyFaceRecognitionMapper.insertPartyFaceRecognition(partyFaceRecognition);
         // 调用算法服务
         String rspCode = "";
@@ -107,9 +94,9 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         Integer opStatus = 1;
         try {
             // 发送请求添加subject
-            HttpResponse response = HttpRequest.post(URL_ADD_SUBJECT)
+            HttpResponse response = HttpRequest.post(FaceConstant.URL_ADD_SUBJECT)
                     .body("{\"subject\":\"" + subject.getSubject() + "\"}")
-                    .header("x-api-key", API_KEY)
+                    .header("x-api-key", FaceConstant.API_KEY)
                     .execute();
             // 解析返回结果
             rspCode = String.valueOf(response.getStatus());
@@ -132,8 +119,6 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         return AjaxResult.success(partyFaceRecognition);
     }
 
-
-
     @Override
     public AjaxResult uploadFace(String subject, MultipartFile file) {
         // 保存数据库
@@ -149,7 +134,7 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         partyFaceRecognition.setOpType(2);
         partyFaceRecognition.setOpStatus(0);
         partyFaceRecognition.setCreateTime(DateUtils.getNowDate());
-        partyFaceRecognition.setUserTableId(getUserTableId(FACE_RECOGNITION_TABLE_NAME, userId, 0));
+        partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
         partyFaceRecognitionMapper.insertPartyFaceRecognition(partyFaceRecognition);
         // 调用算法服务
         String rspCode = "";
@@ -158,9 +143,9 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         try {
             File imageFile = new File(filePath);
             // 发送请求添加subject
-            HttpResponse response = HttpRequest.post(URL_UPLOAD_FACE + subject)
+            HttpResponse response = HttpRequest.post(FaceConstant.URL_UPLOAD_FACE + subject)
                     .form("file",imageFile)
-                    .header("x-api-key", API_KEY)
+                    .header("x-api-key", FaceConstant.API_KEY)
                     .execute();
             // 解析返回结果
             rspCode = String.valueOf(response.getStatus());
@@ -184,7 +169,43 @@ public class CompreFaceServiceImpl implements CompreFaceService {
     }
 
     @Override
-    public AjaxResult recognizeFace(MultipartFile file) {
+    public AjaxResult recognizeFace(Long meetingId,MultipartFile file) {
+
+        PartyFaceRecognition recognitionResult = recognizeFace2AI(meetingId,file);
+        if (recognitionResult.getOpStatus() != 1 || StringUtils.isEmpty(recognitionResult.getRspCode())
+                || !String.valueOf(HttpStatus.HTTP_OK).equalsIgnoreCase(recognitionResult.getRspCode())) {
+            return AjaxResult.error("调用AI算法人脸识别失败");
+        }
+
+        RecognizeFaceRsp recognizeFaceRsp = JSONObject.parseObject(recognitionResult.getRspMsg(), RecognizeFaceRsp.class);
+        List<RecognizeFaceRspResult> resultList = recognizeFaceRsp.getResult();
+        if (CollectionUtils.isEmpty(resultList)) {
+            log.info("recognizeFace result is empty,meetingId:{}",meetingId);
+            return AjaxResult.success("recognizeFace success,but result is empty");
+        }
+        // 找出所有的id_人名集合
+        Map<String,BigDecimal> memberMap = new HashMap<>();
+        for (RecognizeFaceRspResult result : resultList) {
+            if (CollectionUtils.isEmpty(result.getSubjects())) {
+                continue;
+            }
+            RecognizeFaceRspResultSubject subject = result.getSubjects().get(0);
+            String mapKey = subject.getSubject();
+            BigDecimal mapValue = subject.getSimilarity();
+            if (!memberMap.containsKey(mapKey)) {
+                memberMap.put(mapKey,mapValue);
+            }else {
+                BigDecimal oldValue = memberMap.get(mapKey);
+                if (oldValue.compareTo(mapValue) < 0) {
+                    memberMap.put(mapKey,mapValue);
+                }
+            }
+        }
+
+        return AjaxResult.success(memberMap);
+    }
+
+    private PartyFaceRecognition recognizeFace2AI(Long meetingId, MultipartFile file) {
         Long userId = SecurityUtils.getLoginUser().getUserId();
         Map<String,String> fileMap = uploadFile(file);
         JSONObject reqParam = new JSONObject();
@@ -195,8 +216,9 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         partyFaceRecognition.setReqParam(reqParam.toJSONString());
         partyFaceRecognition.setOpType(3);
         partyFaceRecognition.setOpStatus(0);
+        partyFaceRecognition.setMeetingId(meetingId);
         partyFaceRecognition.setCreateTime(DateUtils.getNowDate());
-        partyFaceRecognition.setUserTableId(getUserTableId(FACE_RECOGNITION_TABLE_NAME, userId, 0));
+        partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
         partyFaceRecognitionMapper.insertPartyFaceRecognition(partyFaceRecognition);
         // 调用算法服务
         String rspCode = "";
@@ -205,9 +227,9 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         try {
             File imageFile = new File(filePath);
             // 发送请求添加subject
-            HttpResponse response = HttpRequest.post(URL_FACE_RECOGNITION)
+            HttpResponse response = HttpRequest.post(FaceConstant.URL_FACE_RECOGNITION)
                     .form("file",imageFile)
-                    .header("x-api-key", API_KEY)
+                    .header("x-api-key", FaceConstant.API_KEY)
                     .execute();
             // 解析返回结果
             rspCode = String.valueOf(response.getStatus());
@@ -227,7 +249,7 @@ public class CompreFaceServiceImpl implements CompreFaceService {
             partyFaceRecognition.setUpdateTime(DateUtils.getNowDate());
             partyFaceRecognitionMapper.updatePartyFaceRecognition(partyFaceRecognition);
         }
-        return AjaxResult.success(partyFaceRecognition);
+        return partyFaceRecognition;
     }
 
     @Override
@@ -291,7 +313,7 @@ public class CompreFaceServiceImpl implements CompreFaceService {
             partyFaceRecognition.setOpStatus(0);
             partyFaceRecognition.setCreateTime(DateUtils.getNowDate());
             partyFaceRecognition.setMemberId(partyMemberFace.getMemberId());
-            partyFaceRecognition.setUserTableId(getUserTableId(FACE_RECOGNITION_TABLE_NAME, userId, 0));
+            partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
             partyFaceRecognitionMapper.insertPartyFaceRecognition(partyFaceRecognition);
         }else {
             partyFaceRecognition = subjectList.get(0);
@@ -303,9 +325,9 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         File imageFile = downloadFile(partyMemberFace.getPicPath());
         try {
             // 发送请求添加subject
-            HttpResponse response = HttpRequest.post(URL_UPLOAD_FACE + subject)
+            HttpResponse response = HttpRequest.post(FaceConstant.URL_UPLOAD_FACE + subject)
                     .form("file",imageFile)
-                    .header("x-api-key", API_KEY)
+                    .header("x-api-key", FaceConstant.API_KEY)
                     .execute();
             // 解析返回结果
             rspCode = String.valueOf(response.getStatus());
@@ -342,7 +364,7 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         partyFaceRecognition.setOpType(1);
         partyFaceRecognition.setOpStatus(0);
         partyFaceRecognition.setCreateTime(DateUtils.getNowDate());
-        partyFaceRecognition.setUserTableId(getUserTableId(FACE_RECOGNITION_TABLE_NAME, userId, 0));
+        partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
         partyFaceRecognition.setMemberId(partyMemberFace.getMemberId());
         partyFaceRecognitionMapper.insertPartyFaceRecognition(partyFaceRecognition);
         // 调用算法服务
@@ -351,9 +373,9 @@ public class CompreFaceServiceImpl implements CompreFaceService {
         Integer opStatus = 1;
         try {
             // 发送请求添加subject
-            HttpResponse response = HttpRequest.post(URL_ADD_SUBJECT)
+            HttpResponse response = HttpRequest.post(FaceConstant.URL_ADD_SUBJECT)
                     .body("{\"subject\":\"" + subject + "\"}")
-                    .header("x-api-key", API_KEY)
+                    .header("x-api-key", FaceConstant.API_KEY)
                     .execute();
             // 解析返回结果
             rspCode = String.valueOf(response.getStatus());
@@ -413,7 +435,7 @@ public class CompreFaceServiceImpl implements CompreFaceService {
     }
 
     private static File downloadFile(String imageUrl) {
-        String filePath = FILE_TEMP_PATH + UUID.randomUUID().toString() + ".png";
+        String filePath = FaceConstant.FILE_TEMP_PATH + UUID.randomUUID().toString() + ".png";
         // 下载文件
         HttpUtil.downloadFile(imageUrl, filePath);
         log.info("download file success,file path : {}:" ,filePath);

+ 7 - 1
inspur-ai/src/main/resources/mapper/PartyFaceRecognitionMapper.xml

@@ -15,10 +15,11 @@
         <result property="updateTime"    column="update_time"    />
         <result property="userTableId"    column="user_table_id"    />
         <result property="memberId"    column="member_id"    />
+        <result property="meetingId"    column="meeting_id"    />
     </resultMap>
 
     <sql id="selectPartyFaceRecognitionVo">
-        select id, req_param, rsp_code, rsp_msg, op_type, op_status, create_time, update_time,user_table_id,member_id from party_face_recognition
+        select id, req_param, rsp_code, rsp_msg, op_type, op_status, create_time, update_time,user_table_id,member_id,meeting_id from party_face_recognition
     </sql>
 
     <select id="selectPartyFaceRecognitionList" parameterType="PartyFaceRecognition" resultMap="PartyFaceRecognitionResult">
@@ -31,7 +32,9 @@
             <if test="opStatus != null "> and op_status = #{opStatus}</if>
             <if test="userTableId != null "> and user_table_id = #{userTableId}</if>
             <if test="memberId != null "> and member_id = #{memberId}</if>
+            <if test="meetingId != null "> and meeting_id = #{meetingId}</if>
         </where>
+        order by create_time desc
     </select>
 
     <select id="selectPartyFaceRecognitionById" parameterType="Long" resultMap="PartyFaceRecognitionResult">
@@ -51,6 +54,7 @@
             <if test="updateTime != null">update_time,</if>
             <if test="userTableId != null">user_table_id,</if>
             <if test="memberId != null">member_id,</if>
+            <if test="meetingId != null">meeting_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="reqParam != null">#{reqParam},</if>
@@ -62,6 +66,7 @@
             <if test="updateTime != null">#{updateTime},</if>
             <if test="userTableId != null">#{userTableId},</if>
             <if test="memberId != null">#{memberId},</if>
+            <if test="meetingId != null">#{meetingId},</if>
         </trim>
     </insert>
 
@@ -76,6 +81,7 @@
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="memberId != null">member_id = #{memberId},</if>
+            <if test="meetingId != null">meeting_id = #{meetingId},</if>
         </trim>
         where id = #{id}
     </update>

+ 10 - 0
inspur-party/src/main/java/com/inspur/mapper/PartyAttendanceRecordMapper.java

@@ -145,4 +145,14 @@ public interface PartyAttendanceRecordMapper
      * @param partyAttendanceRecord
      */
     void updatePartyAttendanceRecordByMeetingAndMemeber(PartyAttendanceRecord partyAttendanceRecord);
+
+    /**
+     * 根据会议id和人员id修改考勤记录
+     * @param meetingId
+     * @param memberId
+     * @param attendanceStatus
+     */
+    public void updateStatusByMeetingIdAndMemberId(@Param("meetingId") Long meetingId,
+                                                   @Param("memberId") Long memberId,
+                                                   @Param("attendanceStatus") Integer attendanceStatus);
 }

+ 5 - 0
inspur-party/src/main/java/com/inspur/service/partywork/IPartyMeetingInfoService.java

@@ -1,10 +1,12 @@
 package com.inspur.service.partywork;
 
+import com.inspur.common.core.domain.AjaxResult;
 import com.inspur.domain.app.PartyAppUser;
 import com.inspur.domain.partywork.PartyMeetingFollow;
 import com.inspur.domain.partywork.PartyMeetingInfo;
 import com.inspur.domain.partywork.PartyMeetingVo;
 import com.inspur.domain.screen.MenuDataReqVo;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -159,4 +161,7 @@ public interface IPartyMeetingInfoService
      * @return
      */
     public int meetingSign(PartyAppUser partyAppUser);
+
+
+    public AjaxResult recognizeFace(Long meetingId, MultipartFile file);
 }

+ 9 - 0
inspur-party/src/main/java/com/inspur/service/partywork/IRemoteControlService.java

@@ -1,6 +1,7 @@
 package com.inspur.service.partywork;
 
 import com.inspur.common.core.domain.AjaxResult;
+import com.inspur.common.core.page.TableDataInfo;
 import com.inspur.netty.message.push.UrlControl;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -66,4 +67,12 @@ public interface IRemoteControlService {
      * @return
      */
     public AjaxResult filePlayEnd(Integer deviceId);
+
+    /**
+     * 下发拍照签到控制
+     * @param meetingId
+     * @param deviceId
+     * @return
+     */
+    public AjaxResult takePhotoSign(Long meetingId, Long deviceId);
 }

+ 153 - 4
inspur-party/src/main/java/com/inspur/service/partywork/impl/PartyMeetingInfoServiceImpl.java

@@ -1,6 +1,9 @@
 package com.inspur.service.partywork.impl;
 
-import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpStatus;
+import com.alibaba.fastjson2.JSONObject;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.WriterException;
 import com.google.zxing.client.j2se.MatrixToImageWriter;
@@ -8,18 +11,24 @@ import com.google.zxing.common.BitMatrix;
 import com.google.zxing.qrcode.QRCodeWriter;
 import com.inspur.common.config.InspurConfig;
 import com.inspur.common.constant.Constants;
+import com.inspur.common.core.domain.AjaxResult;
 import com.inspur.common.core.domain.entity.SysUser;
 import com.inspur.common.exception.ServiceException;
 import com.inspur.common.utils.DateUtils;
 import com.inspur.common.utils.LibreOfficeConvertUtil;
 import com.inspur.common.utils.SecurityUtils;
-import com.inspur.common.utils.spring.SpringUtils;
+import com.inspur.common.utils.file.FileUploadUtils;
 import com.inspur.domain.app.PartyAppUser;
-import com.inspur.domain.app.PartyMemberInfoVo;
 import com.inspur.domain.partyscreen.PartyMenu;
 import com.inspur.domain.partywork.*;
 import com.inspur.domain.screen.MenuDataReqVo;
-import com.inspur.dt.service.DengTaSyncService;
+import com.inspur.face.common.FaceConstant;
+import com.inspur.face.domain.PartyFaceRecognition;
+import com.inspur.face.domain.RecognizeFaceRsp;
+import com.inspur.face.domain.RecognizeFaceRspResult;
+import com.inspur.face.domain.RecognizeFaceRspResultSubject;
+import com.inspur.face.mapper.PartyFaceRecognitionMapper;
+import com.inspur.face.service.impl.CompreFaceServiceImpl;
 import com.inspur.framework.config.ServerConfig;
 import com.inspur.framework.manager.AsyncManager;
 import com.inspur.mapper.*;
@@ -41,6 +50,8 @@ import org.apache.commons.fileupload.disk.DiskFileItem;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.jodconverter.office.OfficeManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.MediaType;
@@ -54,6 +65,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.math.BigDecimal;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.util.*;
@@ -70,6 +82,7 @@ import static com.inspur.common.utils.PageUtils.startPage;
 @Service
 public class PartyMeetingInfoServiceImpl implements IPartyMeetingInfoService
 {
+    private static final Logger log = LoggerFactory.getLogger(PartyMeetingInfoServiceImpl.class);
     @Autowired
     private PartyMeetingInfoMapper partyMeetingInfoMapper;
 
@@ -109,6 +122,9 @@ public class PartyMeetingInfoServiceImpl implements IPartyMeetingInfoService
     @Autowired
     private SysUserMapper sysUserMapper;
 
+    @Autowired
+    private PartyFaceRecognitionMapper partyFaceRecognitionMapper;
+
 
     @Value("${netty.idUrl}")
     private String nettyIdUrl;
@@ -1026,4 +1042,137 @@ public class PartyMeetingInfoServiceImpl implements IPartyMeetingInfoService
         String userName = sysUser.getUserName();
         PushMessageUtil.pushMessageAndIdToRemote(userName,messageType,meetingId,nettyIdUrl);
     }
+
+    @Override
+    public AjaxResult recognizeFace(Long meetingId, MultipartFile file) {
+
+        PartyFaceRecognition recognitionResult = recognizeFace2AI(meetingId,file);
+        if (recognitionResult.getOpStatus() != 1 || com.inspur.common.utils.StringUtils.isEmpty(recognitionResult.getRspCode())
+                || !String.valueOf(HttpStatus.HTTP_OK).equalsIgnoreCase(recognitionResult.getRspCode())) {
+            return AjaxResult.error("调用AI算法人脸识别失败");
+        }
+
+        RecognizeFaceRsp recognizeFaceRsp = JSONObject.parseObject(recognitionResult.getRspMsg(), RecognizeFaceRsp.class);
+        List<RecognizeFaceRspResult> resultList = recognizeFaceRsp.getResult();
+        if (CollectionUtils.isEmpty(resultList)) {
+            log.info("recognizeFace result is empty,meetingId:{}",meetingId);
+            return AjaxResult.success("recognizeFace success,but result is empty");
+        }
+        // 找出所有的id_人名集合
+        Map<String, BigDecimal> memberMap = new HashMap<>();
+        for (RecognizeFaceRspResult result : resultList) {
+            if (CollectionUtils.isEmpty(result.getSubjects())) {
+                continue;
+            }
+            RecognizeFaceRspResultSubject subject = result.getSubjects().get(0);
+            String mapKey = subject.getSubject();
+            BigDecimal mapValue = subject.getSimilarity();
+            if (!memberMap.containsKey(mapKey)) {
+                memberMap.put(mapKey,mapValue);
+            }else {
+                BigDecimal oldValue = memberMap.get(mapKey);
+                if (oldValue.compareTo(mapValue) < 0) {
+                    memberMap.put(mapKey,mapValue);
+                }
+            }
+        }
+        // 对map进行遍历 更新签到结果
+        memberMap.keySet().stream().forEach(key -> {
+            String[] keyArr = key.split("_");
+            Long memberId = Long.valueOf(keyArr[0]);
+            Integer attendanceStatus = 1;
+            BigDecimal similarity = memberMap.get(key);
+            if (similarity.compareTo(new BigDecimal(0.95)) < 0) {
+                log.info("人脸识别相似度小于0.95,memberId:{},meetingId:{}",memberId,meetingId);
+            }else {
+                partyAttendanceRecordMapper.updateStatusByMeetingIdAndMemberId(meetingId,memberId,attendanceStatus);
+            }
+        });
+
+        return AjaxResult.success(memberMap);
+    }
+
+    private PartyFaceRecognition recognizeFace2AI(Long meetingId, MultipartFile file) {
+        Long userId = SecurityUtils.getLoginUser().getUserId();
+        Map<String,String> fileMap = uploadFile(file);
+        JSONObject reqParam = new JSONObject();
+        reqParam.put("url", fileMap.get("url"));
+        String filePath = getFilePathByUrl(fileMap.get("url"));
+        reqParam.put("filePath", filePath);
+        PartyFaceRecognition partyFaceRecognition = new PartyFaceRecognition();
+        partyFaceRecognition.setReqParam(reqParam.toJSONString());
+        partyFaceRecognition.setOpType(3);
+        partyFaceRecognition.setOpStatus(0);
+        partyFaceRecognition.setMeetingId(meetingId);
+        partyFaceRecognition.setCreateTime(DateUtils.getNowDate());
+        partyFaceRecognition.setUserTableId(getUserTableId(FaceConstant.FACE_RECOGNITION_TABLE_NAME, userId, 0));
+        partyFaceRecognitionMapper.insertPartyFaceRecognition(partyFaceRecognition);
+        // 调用算法服务
+        String rspCode = "";
+        String rspMsg = "";
+        Integer opStatus = 1;
+        try {
+            File imageFile = new File(filePath);
+            // 发送请求添加subject
+            HttpResponse response = HttpRequest.post(FaceConstant.URL_FACE_RECOGNITION)
+                    .form("file",imageFile)
+                    .header("x-api-key", FaceConstant.API_KEY)
+                    .execute();
+            // 解析返回结果
+            rspCode = String.valueOf(response.getStatus());
+            rspMsg = response.body();
+            if (!String.valueOf(HttpStatus.HTTP_OK).equals(rspCode)) {
+                opStatus = 2;
+                log.info("recognizeFace error,file:{},rspMsg:{}",fileMap.get("url"),rspMsg);
+            }
+        }catch (Exception e) {
+            opStatus = 2;
+            rspMsg = e.getMessage();
+            log.info("recognizeFace error,file:{}",fileMap.get("url"),e);
+        }finally {
+            partyFaceRecognition.setOpStatus(opStatus);
+            partyFaceRecognition.setRspCode(rspCode);
+            partyFaceRecognition.setRspMsg(rspMsg);
+            partyFaceRecognition.setUpdateTime(DateUtils.getNowDate());
+            partyFaceRecognitionMapper.updatePartyFaceRecognition(partyFaceRecognition);
+        }
+        return partyFaceRecognition;
+    }
+
+    private Map<String, String> uploadFile(MultipartFile file) {
+        Map<String,String> resultMap = new HashMap<>();
+        try
+        {
+            // 上传文件路径
+            String filePath = InspurConfig.getUploadPath();
+            // 上传并返回新文件名称
+            String fileName = FileUploadUtils.upload(filePath, file);
+            String url = serverConfig.getNewUrl() + fileName;
+            resultMap.put("url", url);
+            resultMap.put("fileName", fileName);
+            resultMap.put("newFileName", com.inspur.common.utils.file.FileUtils.getName(fileName));
+            resultMap.put("originalFilename", file.getOriginalFilename());
+            return resultMap;
+        }
+        catch (Exception e)
+        {
+            return null;
+        }
+    }
+
+    private String getFilePathByUrl(String url) {
+        // 本地资源路径
+        String basePath = InspurConfig.getProfile();
+        // 数据库资源地址
+        return basePath + com.inspur.common.utils.StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
+    }
+
+    private Long getUserTableId(String tableName, Long userId,Integer dateType) {
+        SysTableList tableInfo = sysUserTableRelService.selectTableInfoByName(tableName,dateType);
+        Long tableId = tableInfo.getId();
+        SysUserTableRel tableRel = sysUserTableRelService.getRelByUserTableId(userId,tableId);
+        Long userTableId = tableRel.getUserTableId();
+        return userTableId;
+    }
+
 }

+ 13 - 6
inspur-party/src/main/java/com/inspur/service/partywork/impl/RemoteControlServiceImpl.java

@@ -63,7 +63,6 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
     public AjaxResult filePlay(Long id, Integer currentPage, Integer deviceId) {
         // 当前操作用户
         Integer index = currentPage - 1;
-        // String userName = SecurityUtils.getLoginUser().getUser().getUserName();
         List<PartyMeetingFollow> imageList = partyMeetingFollowMapper.selectPartyMeetingFollowByFId(id,2);
         String imageUrl = imageList.get(index).getFileUrl();
         FileControl nettyMessage = new FileControl();
@@ -75,7 +74,6 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
         pushMessage.setMessageType(PushMessageType.CONTROL_FILE_START.getValue());
         pushMessage.setMessageData(reqParam);
         String controlParam = JSON.toJSONString(pushMessage);
-
         // 推送消息
         PcDevice pcDevice = pcDeviceMapper.selectPcDeviceById(deviceId.longValue());
         PushMessageUtil.remoteMeetingControl(pcDevice.getWiredMac(),pcDevice.getWirelessMac(),controlUrl,controlParam);
@@ -105,7 +103,6 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
 
     @Override
     public AjaxResult urlControl(UrlControl param) {
-        // String userName = SecurityUtils.getLoginUser().getUser().getUserName();
         String reqParam = JSON.toJSONString(param);
         PushMessage pushMessage = new PushMessage();
         if (param.getType() == 1) {
@@ -124,7 +121,6 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
 
     @Override
     public AjaxResult startAudio(Long meetingId,Long deviceId) {
-        // String userName = SecurityUtils.getLoginUser().getUser().getUserName();
         PushMessage pushMessage = new PushMessage();
         pushMessage.setMessageType(PushMessageType.CONTROL_AUDIO_START.getValue());
         pushMessage.setMessageData(meetingId);
@@ -138,7 +134,6 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
 
     @Override
     public AjaxResult endAudio(Long meetingId,Long deviceId) {
-        //String userName = SecurityUtils.getLoginUser().getUser().getUserName();
         PushMessage pushMessage = new PushMessage();
         pushMessage.setMessageType(PushMessageType.CONTROL_AUDIO_STOP.getValue());
         pushMessage.setMessageData(meetingId);
@@ -152,7 +147,6 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
 
     @Override
     public AjaxResult takePhoto(Long meetingId,Long deviceId) {
-        //String userName = SecurityUtils.getLoginUser().getUser().getUserName();
         PushMessage pushMessage = new PushMessage();
         pushMessage.setMessageType(PushMessageType.CONTROL_TAKE_PHOTO.getValue());
         pushMessage.setMessageData(meetingId);
@@ -164,6 +158,19 @@ public class RemoteControlServiceImpl implements IRemoteControlService {
         return AjaxResult.success();
     }
 
+    @Override
+    public AjaxResult takePhotoSign(Long meetingId,Long deviceId) {
+        PushMessage pushMessage = new PushMessage();
+        pushMessage.setMessageType(PushMessageType.CONTROL_TAKE_PHOTO_SIGN.getValue());
+        pushMessage.setMessageData(meetingId);
+        String controlParam = JSON.toJSONString(pushMessage);
+        // 推送消息
+        PcDevice pcDevice = pcDeviceMapper.selectPcDeviceById(deviceId);
+        PushMessageUtil.remoteMeetingControl(pcDevice.getWiredMac(),pcDevice.getWirelessMac(),controlUrl,controlParam);
+        log.info("远程控制开始,参数:{}",controlParam);
+        return AjaxResult.success();
+    }
+
     @Override
     public AjaxResult photoUpload(Long meetingId, MultipartFile file) {
         // 上传保存文件

+ 4 - 0
inspur-party/src/main/resources/mapper/PartyAttendanceRecordMapper.xml

@@ -199,4 +199,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <update id="updatePartyAttendanceRecordByMeetingAndMemeber" parameterType="com.inspur.domain.partywork.PartyAttendanceRecord">
         update party_attendance_record set attendance_status = 2  where meeting_id = #{meetingId} and member_id=#{memberId}
     </update>
+
+    <update id="updateStatusByMeetingIdAndMemberId">
+        update party_attendance_record set attendance_status = #{attendanceStatus},sign_Time = now() where meeting_id = #{meetingId} and member_id=#{memberId}
+    </update>
 </mapper>

+ 6 - 1
inspur-pc/src/main/java/com/inspur/netty/message/push/PushMessageType.java

@@ -82,7 +82,12 @@ public enum PushMessageType {
     /**
      * 会议控制 - 拍照指令
      */
-    CONTROL_TAKE_PHOTO("2016");
+    CONTROL_TAKE_PHOTO("2016"),
+
+    /**
+     * 会议控制 - 拍照签到
+     */
+    CONTROL_TAKE_PHOTO_SIGN("2017");
 
     private String value;
 

+ 2 - 2
inspur-ui/.env.development

@@ -1,10 +1,10 @@
 # 页面标题
-VUE_APP_TITLE = 浪潮智慧党建管理平台
+VUE_APP_TITLE = 灯塔智慧党建管理平台
 
 # 开发环境配置
 ENV = 'development'
 
-# 浪潮智慧党建管理平台/开发环境
+# 灯塔智慧党建管理平台/开发环境
 VUE_APP_BASE_API = '/dev-api'
 
 # 路由懒加载

+ 4 - 4
inspur-ui/.env.production

@@ -1,11 +1,11 @@
 # 页面标题
-VUE_APP_TITLE = 浪潮智慧党建管理平台
+VUE_APP_TITLE = 灯塔智慧党建管理平台
 
 # 生产环境配置
 ENV = 'production'
 
-# 浪潮智慧党建管理平台/生产环境
-#VUE_APP_BASE_API = '/party-admin'
+# 灯塔智慧党建管理平台/生产环境
+VUE_APP_BASE_API = '/party-admin'
 #VUE_APP_BASE_API = '/prod-api'
-VUE_APP_BASE_API = 'http://192.168.2.200:8080/party-admin-test'
+#VUE_APP_BASE_API = 'http://192.168.2.200:8080/party-admin-test'
 

+ 2 - 2
inspur-ui/.env.staging

@@ -1,10 +1,10 @@
 # 页面标题
-VUE_APP_TITLE = 浪潮智慧党建管理平台
+VUE_APP_TITLE = 灯塔智慧党建管理平台
 
 NODE_ENV = production
 
 # 测试环境配置
 ENV = 'staging'
 
-# 浪潮智慧党建管理平台/测试环境
+# 灯塔智慧党建管理平台/测试环境
 VUE_APP_BASE_API = '/stage-api'

+ 1 - 1
inspur-ui/package.json

@@ -1,7 +1,7 @@
 {
   "name": "ruoyi",
   "version": "3.8.2",
-  "description": "智慧党建管理系统",
+  "description": "灯塔智慧党建管理系统",
   "author": "浪潮",
   "license": "MIT",
   "scripts": {

BIN
inspur-ui/public/favicon.ico


BIN
inspur-ui/public/favicon.ico_old


+ 9 - 1
inspur-ui/src/api/partywork/face.js

@@ -25,10 +25,18 @@ export function uploadFace2AI(data) {
   })
 }
 
+export function photoSignRecord(data) {
+  return request({
+    url: '/compreface/recognition/signRecord',
+    method: 'get',
+    params: data,
+  });
+}
+
 // 查询人脸识别记录详细
 export function getRecognition(id) {
   return request({
-    url: '/system/recognition/' + id,
+    url: '/compreface/recognition/' + id,
     method: 'get'
   })
 }

+ 8 - 0
inspur-ui/src/api/partywork/remoteControl.js

@@ -67,3 +67,11 @@ export function takePhoto (meetingId,deviceId) {
     params: param
   })
 }
+
+export function takePhotoSign(data) {
+  return request({
+    url: '/remote/control/takePhotoSign',
+    method: 'get',
+    params: data,
+  })
+}

BIN
inspur-ui/src/assets/logo/dt_logo.png


+ 5 - 5
inspur-ui/src/layout/components/Navbar.vue

@@ -13,17 +13,17 @@
       &lt;!&ndash; 1.图标 &ndash;&gt;
       &lt;!&ndash; <el-image style="flex: 1;" :src="logo" fit="contain"></el-image> &ndash;&gt;
       &lt;!&ndash; 2.文字 &ndash;&gt;
-      <label style="color: #fff; font-size: 18px;line-height: 25px; ">智慧党建管理系统</label>
+      <label style="color: #fff; font-size: 18px;line-height: 25px; ">灯塔智慧党建管理系统</label>
 
     </router-link>-->
 
     <!-- <div style="float:left; width: 200px;height: 100%; display: flex; justify-content: center; align-items: center;">
-      <label class="navbarTitle" style="">智慧党建管理系统</label>
+      <label class="navbarTitle" style="">灯塔智慧党建管理系统</label>
     </div> -->
     <div
-      style="float:left; width: 200px;height: 100%; display: flex; justify-content: flex-start; align-items: center;margin-left: 10px;">
-      <img src="@/assets/logo/party.png" style="width: 20px;margin-right: 10px;height: 20px;" />
-      <label class="navbarTitle" style="">智慧党建管理系统</label>
+      style="float:left; width: 230px;height: 100%; display: flex; justify-content: flex-start; align-items: center;margin-left: 10px;">
+      <img src="@/assets/logo/dt_logo.png" style="width: 20px;margin-right: 10px;height: 20px;" />
+      <label class="navbarTitle" style="">灯塔智慧党建管理系统</label>
     </div>
 
     <!-- <div style="float:left;margin-left: 5px; width: 300px;height: 100%;">

+ 1 - 1
inspur-ui/src/layout/components/Sidebar/Logo.vue

@@ -34,7 +34,7 @@
     },
     data() {
       return {
-        title: '智慧党建管理系统',
+        title: '灯塔智慧党建管理系统',
         logo: logoImg
       }
     }

+ 1 - 1
inspur-ui/src/views/index.vue

@@ -3,7 +3,7 @@
     <el-row>
       <el-col :span="18">
         <h1 class="text-jumbo text-ginormous">
-          智慧党建管理系统
+          灯塔智慧党建管理系统
         </h1>
         <h2>您没有访问权限!</h2>
         <h6>对不起,您没有访问权限,请不要进行非法操作!您可以返回列表页</h6>

+ 2 - 2
inspur-ui/src/views/login.vue

@@ -6,7 +6,7 @@
       <el-form ref="loginForm" :model="loginForm" :rules="loginRules">
         <div class="login-form" style="width: 500px">
           <h3 class="title" style="display: flex;justify-content: center;align-items: center;">
-            <el-image style="margin-right: 10px; height: 36px;" :src="logo" fit="contain"></el-image>智慧党建管理系统
+            <el-image style="margin-right: 10px; height: 36px;" :src="logo" fit="contain"></el-image>灯塔智慧党建管理系统
           </h3>
 
 
@@ -79,7 +79,7 @@
     encrypt,
     decrypt
   } from '@/utils/jsencrypt'
-  import logoImg from '@/assets/logo/party.png'
+  import logoImg from '@/assets/logo/dt_logo.png'
   import {
     getThemeStyle,
     saveThemeStyle

+ 5 - 1
inspur-ui/src/views/party_work/meeting/branch_party.vue

@@ -735,7 +735,11 @@ export default {
         this.leaveUserId=response.data.leaveUserId;
         this.open = true;
         this.title = "修改支部党员大会";
-        this.materialOptions = this.form.materialOptions;
+        if (this.form.materialOptions != null) {
+          this.materialOptions = this.form.materialOptions;
+        }else {
+          this.materialOptions = [];
+        }
         if(response.data.attendanceStatus==0){
           this.isAttendance=true;
         }else {

+ 88 - 2
inspur-ui/src/views/party_work/meeting/info.vue

@@ -84,6 +84,39 @@
             <el-button @click="savePhoto" type="primary" >保存</el-button>
           </div>
         </el-tab-pane>
+        <el-tab-pane label="人脸签到">
+          <div style="display: flex;justify-content: center">
+            <div style="width: 30%;height: calc(100vh - 220px)">
+              <div style="font-size: medium;margin-bottom: 10px">人员列表</div>
+              <div style="height: 85%;">
+                <el-table v-loading="loading" :data="attendanceList" height="calc(100vh - 250px)" row-key="id">
+                  <el-table-column label="姓名" align="left" prop="memberName" />
+                  <el-table-column label="出勤情况" align="left" prop="attendanceStatus">
+                    <template slot-scope="scope">
+                      <dict-tag :options="dict.type.sys_attendance_type" :value="scope.row.attendanceStatus"/>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="签到时间" align="left" prop="signTime" />
+                </el-table>
+              </div>
+            </div>
+            <div style="width: 70%;border-left: 1px solid #e6e6e6;">
+              <div style="font-size: medium;margin-bottom: 10px;margin-left: 20px">人脸签到</div>
+              <div v-if="null == faceSignUrl" style="height: calc(100vh - 350px);">
+                <el-empty description=""></el-empty>
+              </div>
+              <div v-else style="height: calc(100vh - 350px);display: flex;justify-content: center;align-items: center;" >
+                <div style="width: 100%; height: calc(100vh - 350px)">
+                  <el-image style="width: 100%;height: 100%;margin: 5px" :src="faceSignUrl"/>
+                </div>
+              </div>
+              <div style="height: 10%;display: flex;justify-content: center;align-items: center;">
+                <el-button  type="primary" @click="photoSign">拍照</el-button>
+                <el-button  type="primary" @click="refreshPhotoSign">刷新</el-button>
+              </div>
+            </div>
+          </div>
+        </el-tab-pane>
         <el-tab-pane label="会议纪要">
           <div style="display: flex;justify-content: center">
             <!-- 计时区域 -->
@@ -149,13 +182,23 @@
 </template>
 <script>
 import {getMeeting, getMeetingFileImage, updateMeeting} from "@/api/partywork/meeting";
-import {endAudio, endFilePlay, filePlay, startAudio, takePhoto, urlControl} from "@/api/partywork/remoteControl";
+import {
+  endAudio,
+  endFilePlay,
+  filePlay,
+  startAudio,
+  takePhoto,
+  takePhotoSign,
+  urlControl
+} from "@/api/partywork/remoteControl";
 import {getToken} from "@/utils/auth";
 import {getAudio, listAudio, summaryMeeting, updateAudioTxt} from "@/api/partywork/meeting_audio";
 import {listDevice} from "@/api/pc/device";
+import {listAttendance} from "@/api/partywork/attendance";
+import {photoSignRecord} from "@/api/partywork/face";
 
 export default {
-  dicts: ['sys_asr_status'],
+  dicts: ['sys_asr_status','sys_attendance_type'],
   data() {
     return {
       meetingId: null,
@@ -189,6 +232,8 @@ export default {
       deviceId: null,
       audioReadOnly: true,
       audioId: null,
+      attendanceList: [],
+      faceSignUrl: null,
     }
   },
   computed: {
@@ -211,6 +256,7 @@ export default {
     this.socketConnect();
     this.refreshAudio();
     this.getDeviceList();
+    this.getAttendanceList();
   },
   destroyed() {
     this.websocket.close();
@@ -220,6 +266,42 @@ export default {
     }
   },
   methods: {
+    refreshPhotoSign() {
+      let param = {
+        meetingId : this.meetingId,
+      }
+      photoSignRecord(param).then(response => {
+        let reqParam = JSON.parse(response.data.reqParam);
+        this.faceSignUrl = reqParam.url;
+        this.getAttendanceList();
+      });
+    },
+
+    photoSign() {
+      if (!this.validDeviceId()) {
+        return;
+      }
+      let param = {
+        meetingId : this.meetingId,
+        deviceId : this.deviceId
+      }
+      takePhotoSign(param).then(response => {
+          this.$modal.msgSuccess("下发拍照成功,请刷新!");
+      });
+    },
+    getAttendanceList() {
+      this.loading = true;
+      let param = {
+        meetingId: this.meetingId,
+        pageNum: 1,
+        pageSize: 200,
+        type: 1
+      }
+      listAttendance(param).then(response => {
+        this.attendanceList = response.rows;
+        this.loading = false;
+      });
+    },
     audioTxtEdit() {
       this.audioReadOnly = false;
       this.$message({
@@ -243,6 +325,10 @@ export default {
       }
       listDevice(param).then(response => {
         this.deviceList = response.rows;
+        this.deviceList.forEach(item => {
+          let online = item.onlineStatus == "1" ? "在线" : "离线";
+          item.deviceName = item.deviceName + "(" + online + ")";
+        });
       })
     },
     summaryGenerate() {

+ 1 - 1
inspur-ui/src/views/register.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="register">
     <el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
-      <h3 class="title">智慧党建管理系统</h3>
+      <h3 class="title">灯塔智慧党建管理系统</h3>
       <el-form-item prop="username">
         <el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
           <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />

+ 1 - 1
inspur-ui/vue.config.js

@@ -7,7 +7,7 @@ function resolve(dir) {
 
 const CompressionPlugin = require('compression-webpack-plugin')
 
-const name = process.env.VUE_APP_TITLE || '智慧党建管理系统' // 网页标题
+const name = process.env.VUE_APP_TITLE || '灯塔智慧党建管理系统' // 网页标题
 
 const port = process.env.port || process.env.npm_config_port || 80 // 端口
 

+ 1 - 1
pom.xml

@@ -9,7 +9,7 @@
     <version>3.8.2</version>
 
     <name>party-admin</name>
-    <description>智慧党建管理系统</description>
+    <description>灯塔智慧党建管理系统</description>
     
     <properties>
         <inspur.version>3.8.2</inspur.version>