소스 검색

Merge remote-tracking branch 'origin/test'

# Conflicts:
#	xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmStaffServiceImpl.java
tags/B.2.6.9_20240116_release
kira 1 년 전
부모
커밋
bd3165b7cd
81개의 변경된 파일1953개의 추가작업 그리고 1299개의 파일을 삭제
  1. +1
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/dto/DmSyncDigitalmanDto.java
  2. +8
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/po/DmVisitRecordsPo.java
  3. +2
    -2
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/domain/dto/DmHolidayDto.java
  4. +5
    -2
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/domain/po/DmHolidayPo.java
  5. +23
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/feign/FeignHolidayService.java
  6. +27
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/feign/factory/FeignHolidayFallbackFactory.java
  7. +8
    -2
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/pass/domain/dto/DmRecognizedMultiRecordsDto.java
  8. +3
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/pass/domain/dto/DmRecognizedRecordsDto.java
  9. +8
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/pass/domain/po/DmRecognizedRecordsPo.java
  10. +1
    -3
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/staff/domain/dto/DmVisitCommonDto.java
  11. +3
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/staff/feign/RemoteVisitorService.java
  12. +2
    -0
      xueyi-api/xueyi-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  13. +13
    -16
      xueyi-auth/src/main/java/com/xueyi/auth/controller/TokenController.java
  14. +7
    -1
      xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/utils/MyDateUtils.java
  15. +19
    -7
      xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DgmanTask.java
  16. +0
    -521
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClient.java
  17. +131
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClientManager.java
  18. +343
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/listener/LlmWebSocketListener.java
  19. +2
    -29
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/controller/DmWebsocketController.java
  20. +0
    -2
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/server/config/ServerConfig.java
  21. +5
    -8
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/controller/DmIntentController.java
  22. +10
    -1
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/LlmContext.java
  23. +15
    -2
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/LlmParam.java
  24. +25
    -11
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/impl/SparkServiceImpl.java
  25. +64
    -70
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/FreeChatTemplate.java
  26. +25
    -28
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/GenerativeKnowledgeTemplate.java
  27. +2
    -14
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MeetingOrderTemplate.java
  28. +2
    -2
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MovieChatTemplate.java
  29. +14
    -2
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/controller/DmHolidayController.java
  30. +2
    -2
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/domain/model/DmHolidayConverter.java
  31. +1
    -1
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/domain/query/DmHolidayQuery.java
  32. +1
    -1
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/manager/IDmHolidayManager.java
  33. +2
    -2
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/manager/impl/DmHolidayManager.java
  34. +2
    -2
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/mapper/DmHolidayMapper.java
  35. +3
    -2
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/service/IDmHolidayService.java
  36. +7
    -4
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/service/impl/IDmHolidayServiceImpl.java
  37. +13
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/digitalmans/manager/impl/DmDigitalmanManager.java
  38. +35
    -10
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/DmMeetingOrdersController.java
  39. +73
    -67
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/api/DmMeetingInnerApiController.java
  40. +0
    -1
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/mapper/DmMeetingRoomsMapper.java
  41. +0
    -1
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/service/impl/DmMeetingOrdersServiceImpl.java
  42. +18
    -14
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/pass/controller/api/DmRecognizedRecordsInnerApiController.java
  43. +2
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/resource/mapper/DmResourcesMapper.java
  44. +22
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/resource/service/impl/DmResourcesServiceImpl.java
  45. +13
    -8
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/resource/service/impl/FaceServiceImpl.java
  46. +13
    -5
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/DmStaffController.java
  47. +28
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/DmVisitorSmsConfigController.java
  48. +0
    -15
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/api/DmStaffInnerApiController.java
  49. +8
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/api/DmVisitorApiController.java
  50. +57
    -117
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/api/DmVisitorInnerApiController.java
  51. +25
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/dto/DmVisitorOperateLogDto.java
  52. +17
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/model/DmVisitorOperateLogConverter.java
  53. +6
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/po/DmEmpAttendancePo.java
  54. +61
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/po/DmVisitorOperateLogPo.java
  55. +21
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/query/DmVisitorOperateLogQuery.java
  56. +0
    -59
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/PassRecordsGraphQLQueryResolver.java
  57. +44
    -10
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitRecordGraphQLMutationResolver.java
  58. +10
    -3
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitRecordsGraphQLQueryResolver.java
  59. +47
    -21
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorGraphQLMutationResolver.java
  60. +1
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorGraphQLQuery.java
  61. +63
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorLogsGraphQLQueryResolver.java
  62. +89
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorPassRecordsGraphQLQueryResolver.java
  63. +0
    -89
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/config/GraphQLConfig.java
  64. +13
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/manager/IDmVisitorOperateLogManager.java
  65. +35
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/manager/impl/DmVisitorOperateLogManager.java
  66. +12
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/mapper/DmVisitorOperateLogMapper.java
  67. +5
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/mapper/DmVisitorsMapper.java
  68. +13
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/IDmVisitorOperateLogService.java
  69. +3
    -5
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmEmpAttendanceServiceImpl.java
  70. +94
    -85
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmStaffServiceImpl.java
  71. +142
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmVisitRecordsServiceImpl.java
  72. +41
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmVisitorOperateLogServiceImpl.java
  73. +2
    -2
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/utils/common/ImageUtil.java
  74. +0
    -21
      xueyi-modules/xueyi-system/src/main/resources/graphql/passRecords.graphqls
  75. +1
    -0
      xueyi-modules/xueyi-system/src/main/resources/graphql/root.graphqls
  76. +24
    -10
      xueyi-modules/xueyi-system/src/main/resources/graphql/visitRecords.graphqls
  77. +36
    -13
      xueyi-modules/xueyi-system/src/main/resources/graphql/visitor.graphqls
  78. +29
    -0
      xueyi-modules/xueyi-system/src/main/resources/graphql/visitorLog.graphqls
  79. +26
    -0
      xueyi-modules/xueyi-system/src/main/resources/graphql/visitorPassRecords.graphqls
  80. +20
    -0
      xueyi-modules/xueyi-system/src/main/resources/mapper/staff/DmVisitorsMapper.xml
  81. +5
    -6
      xueyi-modules/xueyi-tenant/src/main/java/com/xueyi/tenant/tenant/controller/TeTenantController.java

+ 1
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/dto/DmSyncDigitalmanDto.java 파일 보기

@@ -21,6 +21,7 @@ public class DmSyncDigitalmanDto extends DmDigitalmanPo {
protected DmResourcesPo background;
protected DmResourcesPo icon;
protected DmResourcesPo screenOff;
protected List<DmResourcesPo> screenOffList;
protected DmDigitalmanWorktimePo worktime;
protected SysDeptExt workdayHour;
protected String iconPos;


+ 8
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/po/DmVisitRecordsPo.java 파일 보기

@@ -1,6 +1,11 @@
package com.xueyi.system.api.digitalmans.domain.po;

import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.xueyi.common.core.annotation.Excel;
import com.xueyi.common.core.web.tenant.base.TBaseEntity;
import lombok.Data;
@@ -54,6 +59,9 @@ public class DmVisitRecordsPo extends TBaseEntity {

/** 邀约访问日期 */
@Excel(name = "邀约访问日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
protected LocalDate visitDate;

/** 邀约访问时间 */


xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/domain/dto/DmHolidayDto.java → xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/domain/dto/DmHolidayDto.java 파일 보기

@@ -1,7 +1,7 @@
package com.xueyi.system.common.domain.dto;
package com.xueyi.system.api.holiday.domain.dto;


import com.xueyi.system.common.domain.po.DmHolidayPo;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import lombok.Data;
import lombok.EqualsAndHashCode;


xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/domain/po/DmHolidayPo.java → xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/domain/po/DmHolidayPo.java 파일 보기

@@ -1,4 +1,4 @@
package com.xueyi.system.common.domain.po;
package com.xueyi.system.api.holiday.domain.po;

import com.baomidou.mybatisplus.annotation.TableName;
import com.xueyi.common.core.annotation.Excel;
@@ -9,7 +9,10 @@ import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.time.LocalDate;

import static com.xueyi.common.core.constant.basic.EntityConstants.*;
import static com.xueyi.common.core.constant.basic.EntityConstants.DEL_FLAG;
import static com.xueyi.common.core.constant.basic.EntityConstants.REMARK;
import static com.xueyi.common.core.constant.basic.EntityConstants.SORT;
import static com.xueyi.common.core.constant.basic.EntityConstants.STATUS;

@Data
@EqualsAndHashCode(callSuper = true)

+ 23
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/feign/FeignHolidayService.java 파일 보기

@@ -0,0 +1,23 @@
package com.xueyi.system.api.holiday.feign;


import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.system.api.holiday.feign.factory.FeignHolidayFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;

/**
* 短信发送服务
*
* @author yrx
*/
@FeignClient(contextId = "feignHolidayService", value = ServiceConstants.SYSTEM_SERVICE, fallbackFactory = FeignHolidayFallbackFactory.class)
public interface FeignHolidayService {

@GetMapping("/holiday/api/todayIsWorkDay")
AjaxResult todayIsWorkDay(@RequestHeader(SecurityConstants.FROM_SOURCE) String source);

}

+ 27
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/holiday/feign/factory/FeignHolidayFallbackFactory.java 파일 보기

@@ -0,0 +1,27 @@
package com.xueyi.system.api.holiday.feign.factory;

import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.system.api.holiday.feign.FeignHolidayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

/**
* 会议室服务 降级处理
*
* @author xueyi
*/
@Slf4j
@Component
public class FeignHolidayFallbackFactory implements FallbackFactory<FeignHolidayService> {

@Override
public FeignHolidayService create(Throwable throwable) {
return new FeignHolidayService() {
@Override
public AjaxResult todayIsWorkDay(String source) {
return AjaxResult.error("工作日服务调用失败:" + throwable.getMessage());
}
};
}
}

+ 8
- 2
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/pass/domain/dto/DmRecognizedMultiRecordsDto.java 파일 보기

@@ -1,5 +1,6 @@
package com.xueyi.system.api.pass.domain.dto;

import com.alibaba.fastjson2.JSON;
import lombok.Data;

import java.io.Serial;
@@ -26,7 +27,12 @@ public class DmRecognizedMultiRecordsDto {

private String sign;

public final static Integer TYPE_STAFF = 1;
public final static Integer TYPE_STRANGER = 2;
public static final Integer TYPE_STAFF = 1;
public static final Integer TYPE_STRANGER = 2;

@Override
public String toString(){
return JSON.toJSONString(this);
}

}

+ 3
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/pass/domain/dto/DmRecognizedRecordsDto.java 파일 보기

@@ -1,5 +1,6 @@
package com.xueyi.system.api.pass.domain.dto;

import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -28,4 +29,6 @@ public class DmRecognizedRecordsDto extends DmRecognizedRecordsPo {
public final static Integer TYPE_STAFF = 1;
public final static Integer TYPE_STRANGER = 6;

private DmVisitorsDto visitor;

}

+ 8
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/pass/domain/po/DmRecognizedRecordsPo.java 파일 보기

@@ -1,7 +1,12 @@
package com.xueyi.system.api.pass.domain.po;

import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.xueyi.common.core.annotation.Excel;
import com.xueyi.common.core.utils.time.LocalDateTimeSerializer;
import com.xueyi.common.core.web.tenant.base.TBaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -65,6 +70,9 @@ public class DmRecognizedRecordsPo extends TBaseEntity {

/** 识别时间 */
@Excel(name = "识别时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
protected LocalDateTime recognizedTime;

/** 所属组织ID */


+ 1
- 3
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/staff/domain/dto/DmVisitCommonDto.java 파일 보기

@@ -37,9 +37,7 @@ public class DmVisitCommonDto {

private String visitorBase64Img;




private Long visitorId;

public String toSmsJson(String code, String name, String companyName, String companyAddress, String parkInfo){
JSONObject json = new JSONObject();


+ 3
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/staff/feign/RemoteVisitorService.java 파일 보기

@@ -40,6 +40,9 @@ public interface RemoteVisitorService {
public JSONObject visitList(@RequestParam(value = "empId") Long empId,
@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

@GetMapping(value = "/visit/inner-api/visitors")
public JSONObject visitors(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

@GetMapping(value = "/visit/inner-api/list-all")
public JSONObject visitListAll(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);



+ 2
- 0
xueyi-api/xueyi-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일 보기

@@ -11,3 +11,5 @@ com.xueyi.system.api.meeting.feign.factory.RemoteMeetingFallbackFactory
com.xueyi.system.api.resource.feign.factory.RemoteH5ConfigFallbackFactory
com.xueyi.system.api.interfaces.airport.feign.factory.RemotePlaneFallbackFactory
com.xueyi.system.api.sms.feign.factory.RemoteSmsFallbackFactory
com.xueyi.system.api.holiday.feign.factory.RemoteHolidayFallbackFactory
com.xueyi.system.api.holiday.feign.factory.FeignHolidayFallbackFactory

+ 13
- 16
xueyi-auth/src/main/java/com/xueyi/auth/controller/TokenController.java 파일 보기

@@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
@@ -53,10 +54,6 @@ public class TokenController {
@Autowired
private SysLoginService sysLoginService;


@Autowired
private RemoteSmsService smsService;

@Autowired
private RemoteSmsService remoteSmsService;

@@ -66,14 +63,15 @@ public class TokenController {
@Autowired
private RedisService redisService;

@Autowired
private RemoteTenantService tenantService;

@Autowired
private RedisTemplate<String, String> redisTemplate;

@Autowired
private RemoteTenantService tenantService;


private final static String REDIS_LOGIN_CODE_PIX = "saas:login:code:";
private static final String REDIS_LOGIN_CODE_PIX = "saas:login:code:";

@PostMapping("login")
public AjaxResult login(@RequestBody LoginBody form) {
@@ -85,21 +83,20 @@ public class TokenController {

@PostMapping("phoneLogin")
public AjaxResult loginByPhone(@Valid @RequestBody PhoneLoginBody form) {
/*if (!RedisUtil.existed(REDIS_LOGIN_CODE_PIX + form.getPhone())) {
return AjaxResult.error("手机号输入错误或验证码已过期");
} else {
Integer code = (Integer) RedisUtil.getVal(REDIS_LOGIN_CODE_PIX + form.getPhone());
if (null != code && !form.getCode().equals(code.toString())) {
return AjaxResult.error("验证码输入不正确");
}
}*/
R<SysEnterpriseStaff> staffR = tenantService.queryStaff(form.getPhone(), SecurityConstants.INNER);
if (staffR.isFail() || staffR.getData() == null) {
return AjaxResult.error("手机号不正确,清查验");
}

// 用户手机号验证登录
LoginUser userInfo = sysLoginService.loginByPhone(form.getPhone());
if (null == userInfo) {
return AjaxResult.error("手机号不正确,清查验");
}
// 获取登录token
return AjaxResult.success(tokenService.createToken(userInfo));
Map<String, Object> map = tokenService.createToken(userInfo);
map.put("staffId", staffR.getData().getId());//塞入对应staffId
return AjaxResult.success(map);
}

@DeleteMapping("logout")


+ 7
- 1
xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/utils/MyDateUtils.java 파일 보기

@@ -333,13 +333,19 @@ public class MyDateUtils extends org.apache.commons.lang.time.DateUtils {
}

public static LocalDateTime dateToLocalDateTime(Date date) {

return date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();

}

public static LocalDate dateToLocalDate(Date date) {
return date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime().toLocalDate();

}


public static Date localDateToDate(LocalDate date) {
LocalDateTime ldt = date.atStartOfDay();


+ 19
- 7
xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DgmanTask.java 파일 보기

@@ -3,15 +3,15 @@ package com.xueyi.job.task;
import com.alibaba.fastjson2.JSON;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.utils.core.StrUtil;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.security.service.TokenService;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import com.xueyi.system.api.holiday.feign.FeignHolidayService;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.staff.feign.RemoteStaffService;
import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto;
import com.xueyi.tenant.api.tenant.feign.RemoteTenantService;
import org.antlr.runtime.Token;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -36,8 +36,11 @@ public class DgmanTask {
@Autowired
RemoteStaffService staffService;

@Autowired
FeignHolidayService feignHolidayService;

public void ryParams(String params) {
log.info(StrUtil.format("执行有参方法:参数{}", params));
log.info("执行有参方法:参数{}", params);
}

public void dgmanMonitor() {
@@ -46,10 +49,10 @@ public class DgmanTask {
log.info("租户列表获取失败");
return;
}
listR.getData().forEach(item->{
listR.getData().forEach(item->
// 更新租户内数字人信息
remoteManDeviceService.manDeviceListInnerSync(item.getId());
});
remoteManDeviceService.manDeviceListInnerSync(item.getId())
);
log.info("监控心跳执行完成");
}

@@ -65,6 +68,15 @@ public class DgmanTask {

public void initStaffAttendances() {
log.info("=======考勤数据初始化开始。。。。========");
AjaxResult result = feignHolidayService.todayIsWorkDay(SecurityConstants.INNER);
if (result !=null && result.get("data") != null){
DmHolidayPo po = JSON.parseObject(JSON.toJSONString(result.get("data")), DmHolidayPo.class);
if (po.getHoliday() == 1){
log.info("=======今天不是工作日,不进行考勤数据初始化========");
return;
}
}

R<List<TeTenantDto>> listR = tenantService.tenantList();
if (listR.isFail()) {
log.info("租户列表获取失败");


+ 0
- 521
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClient.java 파일 보기

@@ -1,521 +0,0 @@
package com.xueyi.nlt.netty.client;

import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.alibaba.nacos.shaded.com.google.gson.JsonArray;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.common.web.interceptor.ApiRequestInterceptor;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.netty.server.config.ServerConfig;
import com.xueyi.nlt.nlt.domain.vo.LlmQueryVo;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import okhttp3.*;
import org.apache.commons.collections4.CollectionUtils;
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.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.Serializable;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class WebSocketClient extends WebSocketListener {

private static final Logger logger = LoggerFactory.getLogger(WebSocketClient.class);
public static WebSocketClient INSTANCE;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;


@Value("${secret.spark.appId}")
private String appId;

@Value("${secret.spark.apiSecret}")
private String apiSecret;

@Value("${secret.spark.apiKey}")
private String apiKey;
@Value("${secret.spark.hostUrl}")
public String hostUrl;
public final static Object LOCK = new Object();

// public static String APPID = "3d9282da";//从开放平台控制台中获取
// public static String APIKEY = "7c217b3a313f4b66fcc14a8e97f85103";//从开放平台控制台中获取
// public static String APISecret = "ZTRiNDQwMTRlOTlmZDQwMDUwYTdjMDM0";//从开放平台控制台中获取

public WebSocket webSocket;
public static final Gson json = new Gson();
// public static String question = "假设你是一位前台,你需要通过与其他人对话来获取会议相关信息,已知今天是2023-7-19,你需要获取会议日期,开始时间,持续时间,会议地点,会议主题。时间用类似00:00的格式输出。对方的话中可能不包含全部信息,对于未知的信息填充为none。如果所有信息都已知那么commit为true。否则为false。将你获得的信息输出为json格式。对方的话是:“明天下午开个会。从两点开到下午三点,在大会议室开,主题是访客接待”,只输出最后的json。输出只有一行,输出格式为{date:,start_time:,duration:,location:,theme:commit:}。";//可以修改question 内容,来向模型提问
// 定义内存共享变量traceId
public Long traceId;
public String question = "请帮我安排五一出行计划";//可以修改question 内容,来向模型提问
public String systemRole = "";
public List<String> questions = new ArrayList<>();//可以修改question 内容,来向模型提问

public boolean stream = false;
public String curUserId = null;
public String answer = "";
public String answerBuf = "";


@PostConstruct
public void init() {
INSTANCE = this;
INSTANCE.redisTemplate = this.redisTemplate;
INSTANCE.stringRedisTemplate = this.stringRedisTemplate;
INSTANCE.appId = this.appId;
}

public static void main(String[] args) {
synchronized (LOCK) {
try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl("https://spark-api.xf-yun.com/v3.1/chat", "54f6e81f40a31d66d976496de895a7a4", "ZDYyMjNmMTlkYTE0YWRmOWUwZTYxNjYz");
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
WebSocket webSocket = okHttpClient.newWebSocket(request,new WebSocketClient());
LOCK.wait();
System.out.println("查询完成");
} catch (InterruptedException ie) {
ie.printStackTrace();
Thread.currentThread().interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}



// write your code here

}

/**
* 调用讯飞开放平台接口发送消息,并将消息存入redis队列
* @param message
* @param key
*/
public void sendMsg(String message,String key){
LlmQueryVo vo = new LlmQueryVo();
vo.setQuestion(message);
vo.setTemplate(key);
redisTemplate.opsForList().rightPush("group:websocket:quary",vo);
sendMsg(message);
}
public void sendMsg(String message){
question = message;

try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl(hostUrl,apiKey,apiSecret);
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
webSocket = okHttpClient.newWebSocket(request,new WebSocketClient());

} catch (Exception e) {
e.printStackTrace();
}
}
public WebSocketClient sendMsg(List<String> messages){
return this.sendMsg(messages,false, "null");
}
public WebSocketClient sendMsg(List<String> messages,boolean stream,String userId){
this.stream = stream;
this.curUserId = userId;
if (messages.size() / 2 > 0) {
systemRole = messages.get(0);
messages.remove(0);
}
questions = messages;
question = null;

try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl(hostUrl,apiKey,apiSecret);
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
WebSocketClient wsc = new WebSocketClient();
wsc.stream = stream;
wsc.curUserId = userId;
wsc.questions = questions;
wsc.question = question;
wsc.systemRole = systemRole;
wsc.traceId = IdUtil.getSnowflakeNextId();
ServerConfig.currentTraceMap.put(curUserId,wsc.traceId);
System.out.println("wocket客户端:" + wsc.hashCode());
webSocket = okHttpClient.newWebSocket(request,wsc);
return wsc;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//鉴权url
public static String getAuthorizationUrl(String hostUrl , String apikey ,String apisecret) throws Exception {
//获取host
URL url = new URL(hostUrl);
//获取鉴权时间 date
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
System.out.println("format:\n" + format );
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
//获取signature_origin字段
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").
append("date: ").append(date).append("\n").
append("GET ").append(url.getPath()).append(" HTTP/1.1");
System.out.println("signature_origin:\n" + builder);
//获得signatue
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec sp = new SecretKeySpec(apisecret.getBytes(charset),"hmacsha256");
mac.init(sp);
byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset));
String signature = Base64.getEncoder().encodeToString(basebefore);
//获得 authorization_origin
String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"",apikey,"hmac-sha256","host date request-line",signature);
//获得authorization
String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset));
//获取httpurl
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", authorization).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();

return httpUrl.toString();
}

//重写onopen
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
new Thread(()->{
JsonObject frame = new JsonObject();
JsonObject header = new JsonObject();
JsonObject chat = new JsonObject();
JsonObject parameter = new JsonObject();
JsonObject payload = new JsonObject();
JsonObject message = new JsonObject();
JsonObject text = new JsonObject();
JsonArray ja = new JsonArray();

//填充header
header.addProperty("app_id",INSTANCE.appId);
header.addProperty("uid","123456789");
//填充parameter
// chat.addProperty("domain","general"); //1.0版本
chat.addProperty("domain","generalv3"); // 3.0版本
chat.addProperty("random_threshold",0.5);
chat.addProperty("max_tokens",1024);
chat.addProperty("auditing","default");
parameter.add("chat",chat);
if (!StringUtils.isEmpty(systemRole)) {
text = new JsonObject();
//填充payload
text.addProperty("role","system");
text.addProperty("content",systemRole);
ja.add(text);
}
if (!StringUtils.isEmpty(question)) {
text = new JsonObject();
//填充payload
text.addProperty("role","user");
text.addProperty("content",question);
ja.add(text);
}else {
for (int i = 0;i < questions.size();i++) {

text = new JsonObject();
if (i % 2 == 0) {
text.addProperty("role","user");

} else {
text.addProperty("role","assistant");
}
text.addProperty("content",questions.get(i));
System.out.println(text.toString());
ja.add(text);
}
}
// message.addProperty("text",ja.getAsString());
message.add("text",ja);
payload.add("message",message);
frame.add("header",header);
frame.add("parameter",parameter);
frame.add("payload",payload);
System.out.println("frame:\n" + frame.toString());
webSocket.send(frame.toString());


}


).start();
}

//重写onmessage

@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
System.out.println("text:\n" + text);
if (!StringUtils.isEmpty(curUserId)) {
if (ServerConfig.currentTraceMap.containsKey(curUserId) && !ServerConfig.currentTraceMap.get(curUserId).equals(traceId)) {
return;
}
}
synchronized (this) {
ResponseData responseData = json.fromJson(text,ResponseData.class);
try {
// System.out.println("code:\n" + responseData.getHeader().get("code"));
if (0 == responseData.getHeader().get("code").getAsInt()) {
System.out.println("###########");
System.out.println("getStatus: " + responseData.getHeader().get("status").getAsInt());
if (2 != responseData.getHeader().get("status").getAsInt()) {
System.out.println("****************");
Payload pl = json.fromJson(responseData.getPayload(), Payload.class);
JsonArray temp = (JsonArray) pl.getChoices().get("text");
JsonObject jo = (JsonObject) temp.get(0);
answer += jo.get("content").getAsString();
answerBuf += jo.get("content").getAsString();
// System.out.println(answer);
} else {
Payload pl1 = json.fromJson(responseData.getPayload(), Payload.class);
JsonObject jsonObject = (JsonObject) pl1.getUsage().get("text");
int prompt_tokens = jsonObject.get("prompt_tokens").getAsInt();
JsonArray temp1 = (JsonArray) pl1.getChoices().get("text");
JsonObject jo = (JsonObject) temp1.get(0);
answer += jo.get("content").getAsString();
answerBuf += jo.get("content").getAsString();
System.out.println("返回结果为:\n" + answer);

if (INSTANCE.redisTemplate.hasKey("gpt:websocket:1")) {
DmWebSocketMessageVo message = (DmWebSocketMessageVo) INSTANCE.redisTemplate.opsForValue().get("gpt:websocket:1");
if (message != null && StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("birthday")) {
JSONObject birthdayJo = new JSONObject();
birthdayJo.put("content", answer);
birthdayJo.put("timestamp", message.getFormat().get("timestamp"));
INSTANCE.stringRedisTemplate.opsForHash().put("group:nlp" + ":" + message.getFormat().getString("orderId"), "birthday", birthdayJo.toString());
INSTANCE.redisTemplate.delete("gpt:websocket:1");
this.notifyAll();
return;
}
if (message!= null && StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("hireDate")) {
JSONObject birthdayJo = new JSONObject();
birthdayJo.put("content", answer);
birthdayJo.put("timestamp", message.getFormat().get("timestamp"));
INSTANCE.stringRedisTemplate.opsForHash().put("group:nlp" + ":" + message.getFormat().getString("orderId"), "hireDate", birthdayJo.toString());
INSTANCE.redisTemplate.delete("gpt:websocket:1");
this.notifyAll();
return;
}
if (message != null) {
JSONObject preWebsocketJo = message.getFormat();
JSONObject meetingJo = new JSONObject();
meetingJo.put("timestamp",preWebsocketJo.get("timestamp"));
meetingJo.put("content",answer);
INSTANCE.stringRedisTemplate.opsForHash().put("group:nlp" + ":" + preWebsocketJo.getString("orderId"), "meeting", meetingJo.toString());
this.notifyAll();
return;
}
INSTANCE.redisTemplate.delete("gpt:websocket:1");
// 清除systemRole
systemRole = "";

}else {
// 添加上下文
INSTANCE.redisTemplate.opsForList().rightPush("group:nlp:null:-1", questions.get(questions.size() - 1));
INSTANCE.redisTemplate.opsForList().rightPush("group:nlp:null:-1", answer);
// 添加缓存
INSTANCE.stringRedisTemplate.opsForValue().set("group:websocket:content", answer);
}
this.notifyAll();
// webSocket.close(3,"客户端主动断开链接");
//webSocket.close(1000,"客户端主动断开链接");
}
if (this.stream && !StringUtils.isEmpty(curUserId)) {
Channel ch = ServerConfig.sessionMap.get(curUserId);
logger.info("当前ch:{}",ch.id().asLongText());
if (ch != null) {
List<String> ttsList = new ArrayList<>();
JSONObject jo = new JSONObject();
jo.put("action","chat");
jo.put("motion","idle");
jo.put("traceId",traceId);
//去除转义符
answerBuf = answerBuf.replaceAll("[\\r\\n]", "");
//去除引号
answerBuf = answerBuf.replaceAll("\"", "");
// 处理answer,如果包含"。",则将"。"之前的内容发送给前端
while(answerBuf.contains("。") || answerBuf.contains("?") || answerBuf.contains("!") ||
answerBuf.contains("?") || answerBuf.contains("!")) {
String[] temp = answerBuf.split("。|?|!|\\?|\\!");
ttsList.add(temp[0] + answerBuf.charAt(temp[0].length()));
answerBuf = answerBuf.substring(temp[0].length() + 1);
}
if (2 == responseData.getHeader().get("status").getAsInt() && CollectionUtils.isEmpty(ttsList)) {
jo.put("tts",answerBuf);
jo.put("status",2);
logger.info("发送到client:{},id:{},内容:{}",curUserId,ch.id().asLongText(),jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(jo.toJSONString()));
} else {
for (int i = 0;i <ttsList.size();i++) {
if (2 == responseData.getHeader().get("status").getAsInt() && i == ttsList.size() - 1) {
jo.put("status",2);
} else {
jo.put("status",1);
}
jo.put("tts",ttsList.get(i));
String str = jo.toJSONString();
logger.info("发送到client:{},id:{},内容:{}",curUserId,ch.id().asLongText(),jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(str));
}
}
}
}

} else {
// 添加缓存
INSTANCE.stringRedisTemplate.opsForValue().set("group:websocket:content", "-1");
// 判断流式则返回结束状态
if (stream == true) {
Channel ch = ServerConfig.sessionMap.get(curUserId);
if (ch != null) {
JSONObject jo = new JSONObject();
jo.put("action","chat");
jo.put("motion","idle");
jo.put("traceId",traceId);
jo.put("status",2);
jo.put("tts","抱歉,您的问题我无法解答。");
String str = jo.toJSONString();
logger.info("发送到client:{},id:{},内容:{}",curUserId,ch.id().asLongText(),jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(str));
}
}
System.out.println("返回结果错误:\n" + responseData.getHeader().get("code") + responseData.getHeader().get("message"));
this.notifyAll();
}
} catch (Exception e) {
if (StringUtils.isNotEmpty(curUserId)) {
Channel ch = ServerConfig.sessionMap.get(curUserId);
JSONObject jo = new JSONObject();
jo.put("action","chat");
jo.put("motion","idle");
jo.put("traceId",traceId);
jo.put("status",2);
jo.put("tts","大模型出现异常,请稍后重试。");
String str = jo.toJSONString();
logger.info("发生异常client:{},内容:{}",curUserId,jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(str));
}
e.printStackTrace();
this.notifyAll();
}
}

}


//重写onFailure

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
System.out.println(response);
}



class ResponseData{
private JsonObject header;
private JsonObject payload;

public JsonObject getHeader() {
return header;
}

public JsonObject getPayload() {
return payload;
}
}

class Header{
private int code ;
private String message;
private String sid;
private String status;

public int getCode() {
return code;
}

public String getMessage() {
return message;
}

public String getSid() {
return sid;
}

public String getStatus() {
return status;
}
}

class Payload{
private JsonObject choices;
private JsonObject usage;

public JsonObject getChoices() {
return choices;
}

public JsonObject getUsage() {
return usage;
}
}

class Choices{
private int status;
private int seq;
private JsonArray text;

public int getStatus() {
return status;
}

public int getSeq() {
return seq;
}

public JsonArray getText() {
return text;
}
}






}

+ 131
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClientManager.java 파일 보기

@@ -0,0 +1,131 @@
package com.xueyi.nlt.netty.client;

import com.xueyi.nlt.netty.client.listener.LlmWebSocketListener;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Component
public class WebSocketClientManager {

private static final Logger logger = LoggerFactory.getLogger(WebSocketClientManager.class);

private static final int MAX_CONCURRENT_CONNECTIONS = 5;
private static final int CORE_POOL_SIZE = 2;
private static final int MAX_POOL_SIZE = 4;
private static final long KEEP_ALIVE_TIME = 60L;

private ExecutorService connectionPool;
private OkHttpClient client;

@Value("${secret.spark.apiSecret}")
private String apiSecret;

@Value("${secret.spark.apiKey}")
private String apiKey;
@Value("${secret.spark.hostUrl}")
public String hostUrl;


@PostConstruct
public void init() {
ConnectionPool okHttpConnectionPool = new ConnectionPool(MAX_CONCURRENT_CONNECTIONS, KEEP_ALIVE_TIME, TimeUnit.SECONDS);
client = new OkHttpClient.Builder().connectionPool(okHttpConnectionPool).build();
connectionPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
}


public static void main(String[] args) {
LlmContext context = new LlmContext("今天北京天气怎么样");
LlmParam param = new LlmParam();
LlmWebSocketListener listener = new LlmWebSocketListener("12345", param, context,false);
synchronized (listener) {
try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl("https://spark-api.xf-yun.com/v3.1/chat", "54f6e81f40a31d66d976496de895a7a4", "ZDYyMjNmMTlkYTE0YWRmOWUwZTYxNjYz");
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
WebSocket webSocket = okHttpClient.newWebSocket(request,listener);
listener.wait();
System.out.println("查询完成");
} catch (InterruptedException ie) {
ie.printStackTrace();
Thread.currentThread().interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 调用讯飞开放平台接口发送消息
* @param listener
*/

public void startWebSocketClient(LlmWebSocketListener listener) {
connectionPool.execute(() -> {
try {
String authUrl = getAuthorizationUrl(hostUrl, apiKey, apiSecret);
String url = authUrl.replace("https://", "wss://").replace("http://", "ws://");
Request request = new Request.Builder().url(url).build();
WebSocket webSocket = client.newWebSocket(request, listener);
} catch (Exception e) {
logger.error("startWebSocketClient error", e.getStackTrace());
}
});
}

//鉴权url
public static String getAuthorizationUrl(String hostUrl , String apikey ,String apisecret) throws Exception {
//获取host
URL url = new URL(hostUrl);
//获取鉴权时间 date
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
System.out.println("format:\n" + format );
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
//获取signature_origin字段
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").
append("date: ").append(date).append("\n").
append("GET ").append(url.getPath()).append(" HTTP/1.1");
System.out.println("signature_origin:\n" + builder);
//获得signatue
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec sp = new SecretKeySpec(apisecret.getBytes(charset),"hmacsha256");
mac.init(sp);
byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset));
String signature = Base64.getEncoder().encodeToString(basebefore);
//获得 authorization_origin
String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"",apikey,"hmac-sha256","host date request-line",signature);
//获得authorization
String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset));
//获取httpurl
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", authorization).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();

return httpUrl.toString();
}

}

+ 343
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/listener/LlmWebSocketListener.java 파일 보기

@@ -0,0 +1,343 @@
package com.xueyi.nlt.netty.client.listener;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.alibaba.nacos.shaded.com.google.gson.JsonArray;
import com.alibaba.nacos.shaded.com.google.gson.JsonElement;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.nlt.netty.server.config.ServerConfig;
import com.xueyi.nlt.nlt.domain.LlmContent;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;

public class LlmWebSocketListener extends WebSocketListener {

private static final Logger logger = LoggerFactory.getLogger(LlmWebSocketListener.class);

private static final Integer SPARK_RESPONSE_STATUS_FIRST_RESULT = 0;
private static final Integer SPARK_RESPONSE_STATUS_INTERMEDIATE_RESULT = 1;
private static final Integer SPARK_RESPONSE_STATUS_LAST_RESULT = 2;
private static final Double RANDOM_THRESHOLD = 0.5;
protected String appId;

protected LlmParam llmParam;

protected LlmContext llmContext;

public String systemRole = "";
// 是否为流式
protected boolean stream = false;

// 是否关闭websocket
private Boolean wsCloseFlag = false;


public String question = "";//可以修改question 内容,来向模型提问

public List<String> questions = new ArrayList<>();//可以修改question 内容,来向模型提问

public String answer = "";
public String answerBuf = "";

public static final Gson json = new Gson();

public LlmWebSocketListener(String appId, LlmParam llmParam, LlmContext context, boolean stream) {
this.appId = appId;
this.llmParam = llmParam;
this.llmContext = context;
this.stream = stream;
}

@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
new Thread(()->{
try {
JsonObject frame = new JsonObject();
JsonObject header = new JsonObject();
JsonObject chat = new JsonObject();
JsonObject parameter = new JsonObject();
JsonObject payload = new JsonObject();
JsonObject message = new JsonObject();
JsonObject text = new JsonObject();
JsonArray ja = new JsonArray();

//填充header
header.addProperty("app_id",appId);
header.addProperty("uid","123456789");
//填充parameter
// chat.addProperty("domain","general"); //1.0版本
chat.addProperty("domain",llmParam.getModel()); // 3.0版本
chat.addProperty("temperature",llmParam.getTemperature());
chat.addProperty("max_tokens",llmParam.getMaxTokens());
parameter.add("chat",chat);

// 插入大模型上下文
for (LlmContent llmContent : llmContext.getContentList()) {
JsonElement jsonTree = json.toJsonTree(llmContent, LlmContent.class);
ja.add(jsonTree);
}
// message.addProperty("text",ja.getAsString());
message.add("text",ja);
payload.add("message",message);
frame.add("header",header);
frame.add("parameter",parameter);
frame.add("payload",payload);
System.out.println("frame:\n" + frame.toString());
webSocket.send(frame.toString());
// 等待服务端返回完毕后关闭
while (true) {
// System.err.println(wsCloseFlag + "---");
Thread.sleep(200);
if (wsCloseFlag) {
break;
}
}
webSocket.close(1000, "");
} catch (InterruptedException e) {
logger.error("websocket发送消息异常:{}",e.getMessage());
}

}
).start();
}

@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
System.out.println("text:\n" + text);
if (ServerConfig.currentTraceMap.containsKey(llmContext.getDevId()) && !ServerConfig.currentTraceMap.get(llmContext.getDevId()).equals(llmContext.getTraceId())) {
return;
}
ResponseData responseData = json.fromJson(text, ResponseData.class);

synchronized (this) {
// 如果返回的code不等于0,打印错误日志,设置websocket关闭标志位,设置answer为抱歉,您的问题我无法解答。如果为流式调用则向channel发送错误信息
if (0 != responseData.header.code) {
logger.error("返回结果错误:{}" , responseData);
this.wsCloseFlag = true;
this.answer = "抱歉,您的问题我无法解答。";
if (this.stream) {
Channel ch = ServerConfig.sessionMap.get(llmContext.getDevId());
if (ch != null) {
JSONObject jo = formatToChannel("抱歉,您的问题我无法解答。",SPARK_RESPONSE_STATUS_LAST_RESULT,responseData.header.code);
logger.info("发送到client:{},id:{},内容:{}",llmContext.getDevId(),ch.id().asLongText(),jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(jo.toJSONString()));
}
} else {
this.notifyAll();
}
return;
}
try {
System.out.println("###########");
System.out.println("getStatus: " + responseData.header.status);
List<Text> textList = responseData.payload.choices.text;
for (Text temp : textList) {
answer += temp.content;
answerBuf += temp.content;
}
if (stream) {
Channel ch = ServerConfig.sessionMap.get(llmContext.getDevId());
logger.info("当前ch:{}",ch.id().asLongText());
if (ch != null) {
//如果answerBuf为空,说明返回了status为2的结果,直接发送给前端
if (StringUtils.isEmpty(answerBuf)) {
JSONObject jo = formatToChannel(answerBuf,responseData.header.status,responseData.header.code);
logger.info("发送到client:{},id:{},内容:{}",llmContext.getDevId(),ch.id().asLongText(),jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(jo.toJSONString()));
}
// 向数字人推送流式消息,将answerBuf中的内容做拆分,如果包含"。",则将"。"之前的内容以列表形式发送给前端
List<String> ttsList = new ArrayList<>();
//去除转义符
answerBuf = answerBuf.replaceAll("[\\r\\n]", "");
//去除引号
answerBuf = answerBuf.replaceAll("\"", "");
// 处理answer,如果包含"。",则将"。"之前的内容发送给前端
while(answerBuf.contains("。") || answerBuf.contains("?") || answerBuf.contains("!") ||
answerBuf.contains("?") || answerBuf.contains("!")) {
String[] temp = answerBuf.split("。|?|!|\\?|\\!");
ttsList.add(temp[0] + answerBuf.charAt(temp[0].length()));
answerBuf = answerBuf.substring(temp[0].length() + 1);
}
for (int i = 0;i < ttsList.size();i++) {
JSONObject resJo;
if (i < ttsList.size() - 1) {
resJo = formatToChannel(ttsList.get(i),1,responseData.header.code);
} else {
resJo = formatToChannel(ttsList.get(i),responseData.header.status,responseData.header.code);
}
logger.info("发送到client:{},id:{},内容:{}",llmContext.getDevId(),ch.id().asLongText(),resJo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(resJo.toJSONString()));
}
}
}
// 判断当前状态是否为发送完成,如果为发送完成,则打印answer,设置websocket关闭标志位,如果为非流式调用,释放锁。
if (SPARK_RESPONSE_STATUS_LAST_RESULT == responseData.header.status) {
System.out.println("返回结果为:\n" + answer);
//关闭释放资源
this.wsCloseFlag = true;
// 如果是非流式调用,释放锁
if (stream) {
// 讯飞返回status为2时,可能不包含。结尾,所以需要判断answerBuf是否为空,如果不为空,则直接发送给前端
Channel ch = ServerConfig.sessionMap.get(llmContext.getDevId());
logger.info("当前ch:{}",ch.id().asLongText());
if (ch != null) {
if (!StringUtils.isEmpty(answerBuf)) {
JSONObject jo = formatToChannel(answerBuf, responseData.header.status, responseData.header.code);
logger.info("发送到client:{},id:{},内容:{}", llmContext.getDevId(), ch.id().asLongText(), jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(jo.toJSONString()));
}
}
}
else {
this.notifyAll();
}

}
} catch (Exception e) {
logger.error("返回结果错误:{}" , e.getMessage());
this.answer = "大模型出现异常,请稍后重试。";
if (stream) {
Channel ch = ServerConfig.sessionMap.get(llmContext.getDevId());
if (ch != null) {
JSONObject jo = formatToChannel("大模型出现异常,请稍后重试。",SPARK_RESPONSE_STATUS_LAST_RESULT,-1);
logger.info("发生异常client:{},内容:{}",llmContext.getDevId(),jo.toJSONString());
ch.writeAndFlush(new TextWebSocketFrame(jo.toJSONString()));
}
} else {
this.notifyAll();
}
}
}
}

@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
}

@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
super.onClosing(webSocket, code, reason);
}

@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {
super.onFailure(webSocket, t, response);
}

// 定义一个局部方法,从SessionMap中获取获取当前用户的channel,向channel发送JSON格式的Response
public JSONObject formatToChannel(String msg, Integer status,Integer code) {
JSONObject jo = new JSONObject();
jo.put("action","chat");
jo.put("motion","idle");
jo.put("traceId",llmContext.getTraceId());
jo.put("status",status);
jo.put("tts",msg);
jo.put("code",code);
return jo;
}


class ResponseData{
private Header header;
private Payload payload;

public Header getHeader() {
return header;
}

public Payload getPayload() {
return payload;
}
}

class Header{
private int code ;
private String message;
private String sid;
private int status;

public int getCode() {
return code;
}

public String getMessage() {
return message;
}

public String getSid() {
return sid;
}

public int getStatus() {
return status;
}
}

class Payload{
private Choices choices;
private Useage usage;

public Choices getChoices() {
return choices;
}

public Useage getUsage() {
return usage;
}
}

class Choices{
int status;
int seq;
List<Text> text;

public int getStatus() {
return status;
}

public int getSeq() {
return seq;
}

public List<Text> getText() {
return text;
}
}
class Text {
String role;
String content;
}
class Useage{
/** 保留字段,可忽略 */
Integer question_tokens;
/** 包含历史问题的总tokens大小 */
Integer prompt_tokens;
/** 回答的tokens大小 */
Integer completion_tokens;
/** prompt_tokens和completion_tokens的和,也是本次交互计费的tokens大小 */
Integer total_tokens;
}
}

+ 2
- 29
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/controller/DmWebsocketController.java 파일 보기

@@ -2,16 +2,9 @@ package com.xueyi.nlt.netty.controller;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.nlt.domain.vo.DmIntentVo;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.nlt.domain.vo.IntentTemplateVo;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.model.Source;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,7 +22,7 @@ public class DmWebsocketController {
private static final Logger log = LoggerFactory.getLogger(DmWebsocketController.class);

@Autowired
WebSocketClient webSocketClient;
WebSocketClientManager webSocketClientManager;

@Autowired
StringRedisTemplate stringRedisTemplate;
@@ -54,26 +47,6 @@ public class DmWebsocketController {
SimpleDateFormat dateFormat3 = new SimpleDateFormat("MM-dd");
Double timestamp = Double.valueOf((String)jo.get("timestamp"));
String meetingRoom = jo.getString("meetingRoom");
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("birthday")) {
String prefix = "假设你是一名公司前台,你看到" + message.getFormat().get("name")+ "已知今天是他的生日。请你从个人角度输出给他的生日贺词。要求待人平和,具有人情味,用词正式,内容与工作无关。输出只包含你要对他说的话,在20字以内。";
webSocketClient.sendMsg(prefix);
redisTemplate.opsForValue().set("gpt:websocket" + ":" + "1", message);
return R.ok();
}
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("hiredate")) {
String prefix = "假设你是一名公司前台,你看到"+ message.getFormat().get("name")+ ",已知今天是他入职1周年,请你从个人角度说出对他入职周年的祝贺。要求具有人情味,有特色,字数在25字左右,不要提到生日,要带人名。输出只包含你要对他说的话。";
webSocketClient.sendMsg(prefix);
redisTemplate.opsForValue().set("gpt:websocket" + ":" + "1", message);
return R.ok();
}
Date date = new Date(timestamp.longValue());
if (message.getSkillCode().equals("1")) {
String prefix = "假设你是一名公司前台,你看到在你们公司工作的\\"+ jo.getString("orderName")+ "\\,请你从个人角度提醒他参加\\" +
dateFormat3.format(timestamp) + "\\在\\" + meetingRoom + "\\的会,要求语气友好。输出只包含你要对他说的话,在20字左右。";
webSocketClient.sendMsg(prefix);
// 设置缓存
redisTemplate.opsForValue().set("gpt:websocket" + ":" + "1", message);
}
return R.ok();
}
}

+ 0
- 2
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/server/config/ServerConfig.java 파일 보기

@@ -1,7 +1,5 @@
package com.xueyi.nlt.netty.server.config;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.nlt.netty.client.WebSocketClient;
import io.netty.channel.Channel;

import java.util.concurrent.ConcurrentHashMap;


+ 5
- 8
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/controller/DmIntentController.java 파일 보기

@@ -11,7 +11,6 @@ import com.xueyi.common.core.constant.digitalman.SkillConstants.SkillType;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.common.core.utils.DateUtil;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.common.core.utils.core.SpringUtils;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.core.web.validate.V_A;
@@ -33,7 +32,7 @@ import com.xueyi.nlt.api.nlt.domain.vo.response.DmKnowledgeResponse;
import com.xueyi.nlt.api.nlt.feign.RemoteIntentService;
import com.xueyi.nlt.api.nlt.feign.RemoteLandingLlmService;
import com.xueyi.nlt.api.nlt.feign.RemoteQAService;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import com.xueyi.nlt.nlt.context.TerminalSecurityContextHolder;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
@@ -54,8 +53,6 @@ import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.digitalmans.feign.RemoteQuestionanswersService;
import com.xueyi.system.api.digitalmans.feign.RemoteSkillService;
import com.xueyi.system.api.interfaces.airport.domain.vo.PlaneMessageVo;
import com.xueyi.system.api.interfaces.airport.feign.RemotePlaneController;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.feign.RemoteEnterpriseService;
@@ -64,7 +61,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@@ -77,9 +73,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -99,7 +93,7 @@ public class DmIntentController extends BaseController<DmIntentQuery, DmIntentDt
IDmIntentService dmIntentService;

@Autowired
WebSocketClient webSocketClient;
WebSocketClientManager webSocketClientManager;

/** 定义节点名称 */
@Override
@@ -598,6 +592,7 @@ public class DmIntentController extends BaseController<DmIntentQuery, DmIntentDt
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("birthday")) {
String prefix = "假设你是一名公司前台,你看到" + message.getFormat().get("name")+ "已知今天是他的生日。请你从个人角度输出给他的生日贺词。要求待人平和,具有人情味,用词正式,内容与工作无关。输出只包含你要对他说的话,在20字以内。";
LlmContext context = new LlmContext(prefix);
context.setDevId(message.getDevId());
LlmResponse response = sysLlmService.chat(context, new LlmParam());
JSONObject birthdayJo = new JSONObject();
birthdayJo.put("content", response.getContent());
@@ -608,6 +603,7 @@ public class DmIntentController extends BaseController<DmIntentQuery, DmIntentDt
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("hireDate")) {
String prefix = "假设你是一名公司前台,你看到"+ message.getFormat().get("name")+ ",已知今天是他入职" + message.getFormat().get("years")+"周年,请你从个人角度说出对他入职周年的祝贺。要求具有人情味,有特色,字数在25字左右,不要提到生日,要带人名。输出只包含你要对他说的话。";
LlmContext context = new LlmContext(prefix);
context.setDevId(message.getDevId());
LlmResponse response = sysLlmService.chat(context, new LlmParam());
JSONObject hireDateJo = new JSONObject();
hireDateJo.put("content", response.getContent());
@@ -620,6 +616,7 @@ public class DmIntentController extends BaseController<DmIntentQuery, DmIntentDt
String prefix = "假设你是一名公司前台,你看到在你们公司工作的\\"+ jo.getString("orderName")+ "\\,请你从个人角度提醒他参加\\" +
dateFormat4.format(timestamp) + "\\在\\" + meetingRoom + "\\的会,要求语气友好。输出只包含你要对他说的话,在20字左右。";
LlmContext context = new LlmContext(prefix);
context.setDevId(message.getDevId());
LlmResponse response = sysLlmService.chat(context, new LlmParam());
JSONObject meetingJo = new JSONObject();
meetingJo.put("content", response.getContent());


+ 10
- 1
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/LlmContext.java 파일 보기

@@ -1,6 +1,7 @@
package com.xueyi.nlt.nlt.domain;

import com.alibaba.fastjson2.JSONArray;
import com.xueyi.common.core.utils.core.IdUtil;
import lombok.Data;
import lombok.NoArgsConstructor;

@@ -10,14 +11,22 @@ import java.util.List;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
public class LlmContext implements Serializable {

private String devId;
private List<LlmContent> contentList;

private Long traceId;


public LlmContext() {
// 创建随机的traceId
traceId = IdUtil.getSnowflakeNextId();
contentList = new ArrayList<>();
}

public LlmContext(String message) {
traceId = IdUtil.getSnowflakeNextId();
contentList = new ArrayList<>();
LlmContent ctx = new LlmContent("user",message);
contentList.add(ctx);


+ 15
- 2
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/LlmParam.java 파일 보기

@@ -5,13 +5,26 @@ import lombok.Data;
@Data
public class LlmParam {

// 模型选择
protected String llm;
protected Integer maxTokens;
protected Double temperature;
protected Integer topK;

// 星火大模型
protected String model;
protected String randomThreshold;

/**
* 构造函数(无参数)
* 默认为星火大模型
*/
public LlmParam() {
this.llm = "spark";
this.model = "generalv3";
this.maxTokens = 1024;
this.temperature = 0.75;
this.topK = 1;
this.temperature = 0.5;
this.topK = 4;

}
}

+ 25
- 11
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/impl/SparkServiceImpl.java 파일 보기

@@ -1,13 +1,16 @@
package com.xueyi.nlt.nlt.service.impl;

import com.xueyi.common.core.utils.core.SpringUtils;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import com.xueyi.nlt.netty.client.listener.LlmWebSocketListener;
import com.xueyi.nlt.netty.server.config.ServerConfig;
import com.xueyi.nlt.nlt.domain.LlmContent;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
import com.xueyi.nlt.nlt.domain.LlmResponse;
import com.xueyi.nlt.nlt.service.ISysLlmService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@@ -20,26 +23,35 @@ import java.util.stream.Collectors;
public class SparkServiceImpl implements ISysLlmService {

@Autowired
WebSocketClient webSocketClient;
WebSocketClientManager webSocketClientManager;

@Autowired
private StringRedisTemplate redisTemplate;

@Value("${secret.spark.appId}")
private String appId;

@Override
public LlmResponse chat(LlmContext context, LlmParam param) {
List<String> contentArr = context.getContentList().stream().map(LlmContent::getContent).collect(Collectors.toList());
WebSocketClient socketClient = SpringUtils.getBean(WebSocketClient.class);
webSocketClient = socketClient.sendMsg(contentArr);
synchronized (webSocketClient) {
LlmWebSocketListener listener = new LlmWebSocketListener(appId, param, context,false);
ServerConfig.currentTraceMap.put(context.getDevId(),context.getTraceId());
webSocketClientManager.startWebSocketClient(listener);
synchronized (listener) {
try {
webSocketClient.wait();
listener.wait();

} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
String result = redisTemplate.opsForValue().get("group:websocket:content");
result = webSocketClient.answer;
String result = listener.answer;
// 添加上下文

// // 添加上下文
// INSTANCE.redisTemplate.opsForList().rightPush("group:nlp:null:-1", questions.get(questions.size() - 1));
// INSTANCE.redisTemplate.opsForList().rightPush("group:nlp:null:-1", answer);
// // 添加缓存
// INSTANCE.stringRedisTemplate.opsForValue().set("group:websocket:content", answer);
LlmResponse response = new LlmResponse();
response.setContent(result);
return response;
@@ -50,8 +62,10 @@ public class SparkServiceImpl implements ISysLlmService {
@Override
public LlmResponse stream(LlmContext context, LlmParam param) {
List<String> contentArr = context.getContentList().stream().map(LlmContent::getContent).collect(Collectors.toList());
webSocketClient.sendMsg(contentArr, true,context.getDevId());
LlmResponse response = new LlmResponse();
LlmWebSocketListener listener = new LlmWebSocketListener(appId, param, context,true);
ServerConfig.currentTraceMap.put(context.getDevId(),context.getTraceId());
webSocketClientManager.startWebSocketClient(listener);
LlmResponse response = new LlmResponse();
return response;
}
}

+ 64
- 70
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/FreeChatTemplate.java 파일 보기

@@ -1,11 +1,9 @@
package com.xueyi.nlt.nlt.template;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import com.xueyi.nlt.nlt.context.TerminalSecurityContextHolder;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
@@ -49,87 +47,83 @@ public class FreeChatTemplate implements BaseTemplate{
Long operatorId = TerminalSecurityContextHolder.getOperatorId();
String redisKey = "group:nlp:" + SecurityContextHolder.getLocalMap().get("enterprise_id") + ":" + operatorId;
// 根据content内容调用模版并返回结果
synchronized (WebSocketClient.LOCK) {
// 通过redis获取数字人上下文信息
Long size = redisTemplate.opsForList().size(redisKey);
if (size > 8) {
redisTemplate.opsForList().leftPop(redisKey,2);
}
size = redisTemplate.opsForList().size(redisKey);
List<String> context = new ArrayList<>();
context.add("你是缔智元公司的前台,你叫小智,你是一位数字人。");
context.addAll(redisTemplate.opsForList().range(redisKey,size-6,size));
// 通过redis获取数字人上下文信息
Long size = redisTemplate.opsForList().size(redisKey);
if (size > 8) {
redisTemplate.opsForList().leftPop(redisKey,2);
}
size = redisTemplate.opsForList().size(redisKey);
List<String> context = new ArrayList<>();
context.add("你是缔智元公司的前台,你叫小智,你是一位数字人。");
context.addAll(redisTemplate.opsForList().range(redisKey,size-6,size));

context.add(content);
context.add(content);

//webSocketClient.sendMsg(context);
//webSocketClient.sendMsg(context);

LlmContext llmContext = LlmContext.parse(context,true);
LlmParam param = new LlmParam();
LlmResponse response = sysLlmService.chat(llmContext,param);
String result = response.getContent();
LlmContext llmContext = LlmContext.parse(context,true);
LlmParam param = new LlmParam();
LlmResponse response = sysLlmService.chat(llmContext,param);
String result = response.getContent();

// 处理数据
if (result.contains("我是科大讯飞")) {
result = result.replaceAll("科大讯飞", "缔智元");
}
result = result.replaceAll("认知模型", "数字员工");
result = result.replaceAll("认知智能模型", "数字员工");
if (result.equals("-1")) {
result = "这个问题超出了我无法回答,您可以提出更多关于电影相关问题。";
}
// 处理数据
if (result.contains("我是科大讯飞")) {
result = result.replaceAll("科大讯飞", "缔智元");
}
result = result.replaceAll("认知模型", "数字员工");
result = result.replaceAll("认知智能模型", "数字员工");
if (result.equals("-1")) {
result = "这个问题超出了我无法回答,您可以提出更多关于电影相关问题。";
}

if(!StringUtils.isEmpty(result)){
redisTemplate.opsForList().rightPush(redisKey,content);
redisTemplate.opsForList().rightPush(redisKey,result);
}
JSONObject resultJson = new JSONObject();
resultJson.put("msg",result);
return resultJson;
if(!StringUtils.isEmpty(result)){
redisTemplate.opsForList().rightPush(redisKey,content);
redisTemplate.opsForList().rightPush(redisKey,result);
}
JSONObject resultJson = new JSONObject();
resultJson.put("msg",result);
return resultJson;
}

public JSONObject handle(String dev, String content, boolean stream) {
Long operatorId = TerminalSecurityContextHolder.getOperatorId();
String redisKey = "group:nlp:" + SecurityContextHolder.getLocalMap().get("enterprise_id") + ":" + operatorId;
// 根据content内容调用模版并返回结果
synchronized (WebSocketClient.LOCK) {
// 通过redis获取数字人上下文信息
Long size = redisTemplate.opsForList().size(redisKey);
if (size > 8) {
redisTemplate.opsForList().leftPop(redisKey,2);
}
size = redisTemplate.opsForList().size(redisKey);
List<String> context = new ArrayList<>();
context.add("你是缔智元公司的前台,你叫小智,你是一位数字人,你们公司在北京,你的职能是负责做会议预定和访客预约。");
// 中航信领导来访临时对策
// 判断如果content包含correctWordsMap中的key,则替换为value
for (String key : correctWordsMap.keySet()) {
if (content.contains(key)) {
content = content.replaceAll(key, correctWordsMap.get(key));
}
// 通过redis获取数字人上下文信息
Long size = redisTemplate.opsForList().size(redisKey);
if (size > 8) {
redisTemplate.opsForList().leftPop(redisKey,2);
}
size = redisTemplate.opsForList().size(redisKey);
List<String> context = new ArrayList<>();
context.add("你是缔智元公司的前台,你叫小智,你是一位数字人,你们公司在北京,你的职能是负责做会议预定和访客预约。");
// 中航信领导来访临时对策
// 判断如果content包含correctWordsMap中的key,则替换为value
for (String key : correctWordsMap.keySet()) {
if (content.contains(key)) {
content = content.replaceAll(key, correctWordsMap.get(key));
}

//context.addAll(redisTemplate.opsForList().range(redisKey,size-2,size));
content = "请用简短的话回答下面的问题:" + content;
context.add(content);
//使用stream去除context列表中所有字符串中的引号
context = context.stream().map(s -> s.replaceAll("\"", "")).collect(java.util.stream.Collectors.toList());

//webSocketClient.sendMsg(context);

LlmContext llmContext = LlmContext.parse(context,true);
llmContext.setDevId(dev);
LlmParam param = new LlmParam();
LlmResponse response = sysLlmService.stream(llmContext,param);

JSONObject resultJson = new JSONObject();
resultJson.put("tts","让我想一想。");
resultJson.put("motion","idle");
resultJson.put("status","0");
resultJson.put("action","chat");
return resultJson;
}

//context.addAll(redisTemplate.opsForList().range(redisKey,size-2,size));
content = "请用简短的话回答下面的问题:" + content;
context.add(content);
//使用stream去除context列表中所有字符串中的引号
context = context.stream().map(s -> s.replaceAll("\"", "")).collect(java.util.stream.Collectors.toList());

//webSocketClient.sendMsg(context);

LlmContext llmContext = LlmContext.parse(context,true);
llmContext.setDevId(dev);
LlmParam param = new LlmParam();
LlmResponse response = sysLlmService.stream(llmContext,param);

JSONObject resultJson = new JSONObject();
resultJson.put("tts","让我想一想。");
resultJson.put("motion","idle");
resultJson.put("status","0");
resultJson.put("action","chat");
return resultJson;
}
@Override
public JSONObject handle(String dev, String content, Long tenantId) {


+ 25
- 28
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/GenerativeKnowledgeTemplate.java 파일 보기

@@ -3,7 +3,11 @@ package com.xueyi.nlt.nlt.template;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
import com.xueyi.nlt.nlt.domain.LlmResponse;
import com.xueyi.nlt.nlt.service.ISysLlmService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -16,41 +20,34 @@ public class GenerativeKnowledgeTemplate implements BaseTemplate{

private static final Logger log = LoggerFactory.getLogger(GenerativeKnowledgeTemplate.class);
@Autowired
WebSocketClient webSocketClient;
WebSocketClientManager webSocketClientManager;

@Autowired
private ISysLlmService sysLlmService;

@Autowired
private RedisTemplate<String,String> redisTemplate;

@Override
public JSONObject handle(String devId, String content) {
JSONObject jsonObject = new JSONObject();
// 根据content内容调用模版并返回结果
synchronized (WebSocketClient.LOCK) {

String prefix = "你的任务是[针对给定的文段提出" + (content.length() /100 + 1 ) + "个问题并回答]。文段为:[\"";
String suffix = "\"]。输出为一个JSON数组[{}],每个元素是一个JSON:{“question”:,”answer”:}。不要给出任何解释说明。";
log.info(prefix + content + suffix);
webSocketClient.sendMsg(prefix + content + suffix);
try {
WebSocketClient.LOCK.wait();
String result = (String)redisTemplate.opsForValue().get("group:websocket:content");
try {
JSONArray jsonArray = JSONArray.parseArray(result);
JSONObject jsonObject = new JSONObject();
jsonObject.put("questions",jsonArray);
return jsonObject;
} catch (JSONException je) {
// 返回结果错误,计日志,存log,返回空结果
log.error(je.getMessage(),je);
return new JSONObject();
}

} catch (InterruptedException e) {
log.warn(e.getMessage());
Thread.currentThread().interrupt();
}
String prefix = "你的任务是[针对给定的文段提出" + (content.length() /100 + 1 ) + "个问题并回答]。文段为:[\"";
String suffix = "\"]。输出为一个JSON数组[{}],每个元素是一个JSON:{“question”:,”answer”:}。不要给出任何解释说明。";
log.info(prefix + content + suffix);
LlmContext llmContext = new LlmContext(prefix + content + suffix);
llmContext.setDevId(devId);
LlmParam llmParam = new LlmParam();
LlmResponse response = sysLlmService.chat(llmContext,llmParam);
try {
JSONArray jsonArray = JSONArray.parseArray(response.getContent());
jsonObject.put("questions",jsonArray);
return jsonObject;
} catch (JSONException je) {
// 返回结果错误,计日志,存log,返回空结果
log.error(je.getMessage(),je);
}
return new JSONObject();
return jsonObject;
}

@Override


+ 2
- 14
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MeetingOrderTemplate.java 파일 보기

@@ -2,9 +2,7 @@ package com.xueyi.nlt.nlt.template;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONException;
@@ -15,14 +13,8 @@ import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.digitalman.SkillConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.api.nlt.domain.vo.CoversationSessionVo;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.nlt.config.MeetingParam;
import com.xueyi.nlt.nlt.controller.DmIntentController;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
import com.xueyi.nlt.nlt.domain.LlmResponse;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import com.xueyi.nlt.nlt.domain.vo.MeetingParamVo;
import com.xueyi.nlt.nlt.service.ISysLlmService;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo;
import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import com.xueyi.system.api.meeting.domain.dto.DmMeetingRoomsDto;
@@ -30,23 +22,19 @@ import com.xueyi.system.api.meeting.feign.RemoteMeetingService;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.feign.RemoteEnterpriseService;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
@@ -59,7 +47,7 @@ public class MeetingOrderTemplate implements BaseTemplate {

private static final Logger log = LoggerFactory.getLogger(MeetingOrderTemplate.class);
@Autowired
WebSocketClient webSocketClient;
WebSocketClientManager webSocketClientManager;

// @Autowired
// RemoteMeetingService remoteMeetingService;


+ 2
- 2
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MovieChatTemplate.java 파일 보기

@@ -3,7 +3,7 @@ package com.xueyi.nlt.nlt.template;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.netty.client.WebSocketClientManager;
import com.xueyi.nlt.nlt.context.TerminalSecurityContextHolder;
import com.xueyi.nlt.nlt.domain.LlmContext;
import com.xueyi.nlt.nlt.domain.LlmParam;
@@ -24,7 +24,7 @@ public class MovieChatTemplate implements BaseTemplate{

private static final Logger log = LoggerFactory.getLogger(MovieChatTemplate.class);
@Autowired
WebSocketClient webSocketClient;
WebSocketClientManager webSocketClientManager;

@Autowired
ISysLlmService sysLlmService;


+ 14
- 2
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/controller/DmHolidayController.java 파일 보기

@@ -2,9 +2,11 @@ package com.xueyi.system.common.controller;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.security.annotation.InnerAuth;
import com.xueyi.common.web.annotation.TenantIgnore;
import com.xueyi.common.web.entity.controller.BaseController;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.feign.RemoteHolidayService;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.common.domain.query.DmHolidayQuery;
import com.xueyi.system.common.service.IDmHolidayService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,17 +32,27 @@ public class DmHolidayController extends BaseController<DmHolidayQuery, DmHolida
* 获取今天是否为工作日
*/
@GetMapping("/api/getTodayIsWorkDay")
@TenantIgnore(tenantLine = true)
AjaxResult getTodayIsWorkDay() {
return success(baseService.getTodayHoliday());
}

@GetMapping("/api/todayIsWorkDay")
@TenantIgnore(tenantLine = true)
@InnerAuth
AjaxResult todayIsWorkDay() {
return success(baseService.getTodayHoliday());
}

/**
* 调用外部接口,获取本年度节假日信息
*/
@GetMapping("/getHolidays")
AjaxResult getHolidays() {
JSONObject holidays = holidayService.getHolidays();
return AjaxResult.success();
return AjaxResult.success(holidays);
}



}

+ 2
- 2
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/domain/model/DmHolidayConverter.java 파일 보기

@@ -1,8 +1,8 @@
package com.xueyi.system.common.domain.model;

import com.xueyi.common.core.web.entity.model.BaseConverter;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.common.domain.po.DmHolidayPo;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import com.xueyi.system.common.domain.query.DmHolidayQuery;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;


+ 1
- 1
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/domain/query/DmHolidayQuery.java 파일 보기

@@ -1,5 +1,5 @@
package com.xueyi.system.common.domain.query;
import com.xueyi.system.common.domain.po.DmHolidayPo;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import lombok.Data;
import lombok.EqualsAndHashCode;



+ 1
- 1
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/manager/IDmHolidayManager.java 파일 보기

@@ -1,7 +1,7 @@
package com.xueyi.system.common.manager;

import com.xueyi.common.web.entity.manager.IBaseManager;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.common.domain.query.DmHolidayQuery;

/**


+ 2
- 2
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/manager/impl/DmHolidayManager.java 파일 보기

@@ -3,9 +3,9 @@ package com.xueyi.system.common.manager.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import com.xueyi.system.common.domain.model.DmHolidayConverter;
import com.xueyi.system.common.domain.po.DmHolidayPo;
import com.xueyi.system.common.domain.query.DmHolidayQuery;
import com.xueyi.system.common.manager.IDmHolidayManager;
import com.xueyi.system.common.mapper.DmHolidayMapper;


+ 2
- 2
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/mapper/DmHolidayMapper.java 파일 보기

@@ -2,8 +2,8 @@ package com.xueyi.system.common.mapper;

import com.xueyi.common.datasource.annotation.Master;
import com.xueyi.common.web.entity.mapper.BaseMapper;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.common.domain.po.DmHolidayPo;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import com.xueyi.system.common.domain.query.DmHolidayQuery;

/**


+ 3
- 2
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/service/IDmHolidayService.java 파일 보기

@@ -1,14 +1,15 @@
package com.xueyi.system.common.service;

import com.xueyi.common.web.entity.service.IBaseService;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.common.domain.query.DmHolidayQuery;

import java.time.LocalDate;
import java.util.Date;

public interface IDmHolidayService extends IBaseService<DmHolidayQuery, DmHolidayDto> {

DmHolidayDto getTodayHoliday();

DmHolidayDto isHoliday(Date date);
DmHolidayDto isHoliday(LocalDate date);
}

+ 7
- 4
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/common/service/impl/IDmHolidayServiceImpl.java 파일 보기

@@ -2,7 +2,7 @@ package com.xueyi.system.common.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.xueyi.common.web.entity.service.impl.BaseServiceImpl;
import com.xueyi.system.common.domain.dto.DmHolidayDto;
import com.xueyi.system.api.holiday.domain.dto.DmHolidayDto;
import com.xueyi.system.common.domain.query.DmHolidayQuery;
import com.xueyi.system.common.manager.IDmHolidayManager;
import com.xueyi.system.common.service.IDmHolidayService;
@@ -16,13 +16,16 @@ public class IDmHolidayServiceImpl extends BaseServiceImpl<DmHolidayQuery, DmHol

@Override
public DmHolidayDto getTodayHoliday() {
return isHoliday(new Date());
return isHoliday(LocalDateTimeUtil.now().toLocalDate());
}

@Override
public DmHolidayDto isHoliday(Date date) {
public DmHolidayDto isHoliday(LocalDate date) {
if (date == null) {
return null;
}
DmHolidayQuery query = new DmHolidayQuery();
query.setDate(LocalDateTimeUtil.of(date).toLocalDate());
query.setDate(date);
DmHolidayDto dto = baseManager.selectTodayHoliday(query);
if (dto != null) {
return dto;


+ 13
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/digitalmans/manager/impl/DmDigitalmanManager.java 파일 보기

@@ -20,12 +20,16 @@ import com.xueyi.system.digitalmans.mapper.DmDigitalmanMapper;
import com.xueyi.system.digitalmans.mapper.DmDigitalmanWorktimeMapper;
import com.xueyi.system.digitalmans.mapper.DmModelMapper;
import com.xueyi.system.organize.mapper.SysDeptExtMapper;
import com.xueyi.system.resource.domain.po.DmScreenOffPo;
import com.xueyi.system.resource.mapper.DmResourcesMapper;
import com.xueyi.system.resource.mapper.DmScreenOffMapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
* 数字人基础管理 数据封装层处理
@@ -39,6 +43,8 @@ public class DmDigitalmanManager extends BaseManagerImpl<DmDigitalmanQuery, DmDi

@Autowired
DmDigitalmanExtMapper digitalmanExtMapper;
@Autowired
DmScreenOffMapper screenOffMapper;

@Autowired
DmResourcesMapper dmResourcesMapper;
@@ -140,7 +146,14 @@ public class DmDigitalmanManager extends BaseManagerImpl<DmDigitalmanQuery, DmDi
sdmdto.setIcon(dmResourcesMapper.selectById(mpo.getIconId()));
sdmdto.setIconPos(mpo.getIconPos());
DmResourcesPo screenOffPo = dmResourcesMapper.selectById(mpo.getCurrentScreenOff());
// 获取status为1的屏保
List<Long> screenOffResourceList = screenOffMapper.selectList(Wrappers.<DmScreenOffPo>query().lambda().eq(DmScreenOffPo::getStatus,0)).stream().map(DmScreenOffPo::getResourceId).toList();
List<DmResourcesPo> screenOffList = new ArrayList<>();
if (screenOffResourceList.size() > 0) {
screenOffList = dmResourcesMapper.selectList(Wrappers.<DmResourcesPo>query().lambda().in(DmResourcesPo::getId,screenOffResourceList));
}
sdmdto.setScreenOff(screenOffPo);
sdmdto.setScreenOffList(screenOffList);
sdmdto.setDirection(mpo.getDirection());
System.out.println(sdmdto);
return sdmdto;


+ 35
- 10
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/DmMeetingOrdersController.java 파일 보기

@@ -6,6 +6,8 @@ import com.xueyi.common.core.web.validate.V_A;
import com.xueyi.common.core.web.validate.V_E;
import com.xueyi.common.log.annotation.Log;
import com.xueyi.common.log.enums.BusinessType;
import com.xueyi.common.redis.service.RedisService;
import com.xueyi.common.redis.utils.RedisUtil;
import com.xueyi.common.security.annotation.RequiresPermissions;
import com.xueyi.common.web.entity.controller.BaseController;
import com.xueyi.common.web.response.MyResponse;
@@ -15,6 +17,8 @@ import com.xueyi.system.meeting.domain.model.DmMeetingOrdersConverter;
import com.xueyi.system.meeting.domain.query.DmMeetingOrdersQuery;
import com.xueyi.system.meeting.mapper.DmMeetingOrdersMapper;
import com.xueyi.system.meeting.service.IDmMeetingOrdersService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -30,6 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* 会议室预约管理 业务处理
@@ -39,7 +44,9 @@ import java.util.List;
@RestController
@RequestMapping("/meeting/orders")
public class DmMeetingOrdersController extends BaseController<DmMeetingOrdersQuery, DmMeetingOrdersDto, IDmMeetingOrdersService> {
private static final Logger log = LoggerFactory.getLogger(DmMeetingOrdersController.class);

private static final String REDIS_KEY = "meeting:orders:";
@Autowired
private DmMeetingOrdersConverter dmMeetingOrdersConverter;

@@ -49,6 +56,9 @@ public class DmMeetingOrdersController extends BaseController<DmMeetingOrdersQue
@Autowired
private IDmMeetingOrdersService dmMeetingOrdersService;

@Autowired
private RedisService redisService;

/** 定义节点名称 */
@Override
protected String getNodeName() {
@@ -113,17 +123,32 @@ public class DmMeetingOrdersController extends BaseController<DmMeetingOrdersQue
@RequiresPermissions(Auth.DM_MEETING_ORDERS_LIST)
@GetMapping("/lists")
public JSONObject lists(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId) {
List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findListByDate(dateStr, spaceId);
List<DmMeetingOrdersDto> res = new ArrayList<>();
list.forEach(item -> {
DmMeetingOrdersDto dto = dmMeetingOrdersConverter.mapperDto(item);
dmMeetingOrdersService.fixColumns(dto);
res.add(dto);
});
MyResponse myResponse = new MyResponse();
MyResponse myResponse = new MyResponse(0,"");
List<DmMeetingOrdersDto> res = new ArrayList<>();
if (RedisUtil.existed(REDIS_KEY+dateStr+":"+spaceId)) {
Object obj = redisService.getCacheObject(REDIS_KEY+dateStr+":"+spaceId);
if (!(obj instanceof String)) {
log.info("===lists meeting orders from redis===");
res = redisService.getCacheList(REDIS_KEY+dateStr+":"+spaceId);
} else {
log.info("===empty meeting orders from redis===");
}
} else {
log.info("===lists meeting orders from db===");
List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findListByDate(dateStr, spaceId);
res = list.stream().map(t->{
DmMeetingOrdersDto dto = dmMeetingOrdersConverter.mapperDto(t);
dmMeetingOrdersService.fixColumns(dto);
return dto;
}).toList();
if (!res.isEmpty()) {
redisService.setCacheList(REDIS_KEY+dateStr+":"+spaceId, res, 60L, TimeUnit.SECONDS);
} else {
redisService.setCacheObject(REDIS_KEY+dateStr+":"+spaceId, "empty", 60L, TimeUnit.SECONDS);//避免每次都查数据库,塞入字符串
}
}

myResponse.setData(res);
myResponse.setErrMsg("");
myResponse.setStatus(0);
return myResponse.toJSON();
}



+ 73
- 67
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/api/DmMeetingInnerApiController.java 파일 보기

@@ -73,6 +73,13 @@ import java.util.stream.Collectors;
@RequestMapping("/meeting/inner-api")
public class DmMeetingInnerApiController extends MyBaseApiController {

private static final String START_TIME_KEY = "startTime";
private static final String ORDER_DATE_KEY = "orderDate";
private static final String END_TIME_KEY = "endTime";
private static final String ROBOT_NAME_KEY = "robotName";
private static final String ROOM_ID_KEY = "roomId";
private static final String ERR_MSG = "日期格式不正确";

private static final Logger log = LoggerFactory.getLogger(DmMeetingInnerApiController.class);
@Autowired
private DmMeetingRoomsMapper dmMeetingRoomsMapper;
@@ -200,13 +207,12 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
JSONObject jsonObject = new JSONObject();
jsonObject.put("dateStr", mms2);
jsonObject.put("name", dmStaffPo.getUserName());
//TODO. 发送短信 后期需要获取数字人昵称

DmDigitalmanPo dmDigitalmanPo = digitalmanMapper.selectByCode(digitalmanExtMapper.selectOne(Wrappers.<DmDigitalmanExtPo>query().lambda().eq(DmDigitalmanExtPo::getDeviceId, order.getDevId()).last(SqlConstants.LIMIT_ONE)).getManCode());
if (null!= dmDigitalmanPo && StringUtils.isNotEmpty(dmDigitalmanPo.getName())) {
jsonObject.put("robotName", dmDigitalmanPo.getName());
jsonObject.put(ROBOT_NAME_KEY, dmDigitalmanPo.getName());
} else {
jsonObject.put("robotName", smsProperties.getRobotName());
jsonObject.put(ROBOT_NAME_KEY, smsProperties.getRobotName());
}

send.setDataMap(jsonObject.toJSONString());
@@ -214,7 +220,7 @@ public class DmMeetingInnerApiController extends MyBaseApiController {

}
} catch (Exception e) {
System.err.println(e.getMessage());
log.info(e.getMessage());
e.printStackTrace();
}
// 埋点 预定会议室
@@ -245,7 +251,7 @@ public class DmMeetingInnerApiController extends MyBaseApiController {

@InnerAuth
@GetMapping(value = "/enableOrder/{roomId}/{dateStr}/{startTime}")
public JSONObject queryExist(@PathVariable(name = "roomId") Long roomId, @PathVariable(name = "dateStr") String dateStr, @PathVariable(name = "startTime") String startTime) {
public JSONObject queryExist(@PathVariable(name = ROOM_ID_KEY) Long roomId, @PathVariable(name = "dateStr") String dateStr, @PathVariable(name = START_TIME_KEY) String startTime) {
log.info("dateStr:{}", dateStr);
log.info("startTime:{}", startTime);
DmMeetingRoomsPo room = dmMeetingRoomsMapper.findById(roomId);
@@ -258,12 +264,13 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
if (StringUtils.isEmpty(startTime)) {
return output(ResponseCode.MEETING_ORDER_TIME_ERROR).toJSON();
}
String sTime = startTime,eTime = "";
String sTime = startTime;
String eTime = "";
Date end = MyDateUtils.addMinutes(MyDateUtils.parseStrToDate(dateStr + " " + startTime, MyDateUtils.DEFAULT_NO_SECOND_DATE_PATTERN), 30);
eTime = MyDateUtils.formatDate(end, MyDateUtils.DEFAULT_TIME_PATTERN);

List<DmMeetingOrdersPo> lists = dmMeetingOrdersMapper.queryByOrder(roomId, dateStr, sTime, eTime);
if (lists.size() > 0) {
if (!lists.isEmpty()) {
return output(ResponseCode.MEETING_ORDER_TIME_ERROR).toJSON();
}
return outputSuccess().toJSON();
@@ -271,7 +278,7 @@ public class DmMeetingInnerApiController extends MyBaseApiController {

@InnerAuth
@GetMapping(value = "/enableOrder/{roomId}/{dateStr}/{startTime}/{duration}")
public JSONObject queryExistOrder(@PathVariable(name = "roomId") Long roomId, @PathVariable(name = "dateStr") String dateStr, @PathVariable(name = "startTime") String startTime, @PathVariable(name = "duration") Integer duration) {
public JSONObject queryExistOrder(@PathVariable(name = ROOM_ID_KEY) Long roomId, @PathVariable(name = "dateStr") String dateStr, @PathVariable(name = START_TIME_KEY) String startTime, @PathVariable(name = "duration") Integer duration) {
log.info("startTime:{}", startTime);
DmMeetingRoomsPo room = dmMeetingRoomsMapper.findById(roomId);
if (null == room) {
@@ -283,14 +290,15 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
if (StringUtils.isEmpty(startTime)) {
return output(ResponseCode.MEETING_ORDER_TIME_ERROR).toJSON();
}
String sTime = startTime,eTime = "";
String sTime = startTime;
String eTime = "";
Date end = MyDateUtils.parseStrToDate(dateStr + " " + startTime, MyDateUtils.DEFAULT_NO_SECOND_DATE_PATTERN);
end = MyDateUtils.addMinutes(end, duration);
eTime = MyDateUtils.formatDate(end, MyDateUtils.DEFAULT_TIME_PATTERN);
log.info("roomId:{} dateStr:{} startTime:{} endTime:{} duration:{}", roomId, dateStr, sTime, eTime, duration);

List<DmMeetingOrdersPo> lists = dmMeetingOrdersMapper.queryByOrder(roomId, dateStr, sTime, eTime);
if (lists.size() > 0) {
if (!lists.isEmpty()) {
return output(ResponseCode.MEETING_ORDER_TIME_ERROR).toJSON();
}
return outputSuccess().toJSON();
@@ -310,7 +318,6 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
DmMeetingRoomsPo meetingRoom = dmMeetingRoomsMapper.findById(mro.getSpaceId());
String mms = dateFormat1.format(mro.getOrderDate()) + " " + dateFormat2.format(mro.getStartTime()) + "于" + meetingRoom.getName();

//TODO. 发送短信
DmStaffPo dmStaffPo = dmStaffMapper.selectById(mro.getOrderBy());

SmsReqEntity send = new SmsReqEntity();
@@ -322,7 +329,9 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
jsonObject.put("dateStr", mms);
jsonObject.put("name", dmStaffPo.getUserName());
//TODO. 发送短信 后期需要获取数字人昵称
jsonObject.put("robotName", smsProperties.getRobotName());


jsonObject.put(ROBOT_NAME_KEY, smsProperties.getRobotName());
send.setDataMap(jsonObject.toJSONString());
remoteSmsService.sendSms(send);
}
@@ -357,7 +366,7 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
@PostMapping(value = "/date-lists")
public JSONObject listByDate(@RequestParam("dateStr") String dateStr) {
if (StringUtils.isEmpty(dateStr) || dateStr.length() < 9) {
return output(ResponseCode.ILLEGAL_PARAMETER, "日期格式不正确").toJSON();
return output(ResponseCode.ILLEGAL_PARAMETER, ERR_MSG).toJSON();
}
List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findListByDateStr(dateStr);
List<DmMeetingOrdersDto> res = new ArrayList<>();
@@ -378,7 +387,7 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
@PostMapping(value = "/lists")
public JSONObject listInner(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId) {
if (StringUtils.isEmpty(dateStr) || dateStr.length() < 9) {
return output(ResponseCode.ILLEGAL_PARAMETER, "日期格式不正确").toJSON();
return output(ResponseCode.ILLEGAL_PARAMETER, ERR_MSG).toJSON();
}
List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findListByDate(dateStr, spaceId);
List<DmMeetingOrdersDto> res = new ArrayList<>();
@@ -394,11 +403,11 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
@PostMapping(value = "/lists-all")
public JSONObject listAllInner(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId) {
if (StringUtils.isEmpty(dateStr) || dateStr.length() < 10) {
return output(ResponseCode.ILLEGAL_PARAMETER, "日期格式不正确").toJSON();
return output(ResponseCode.ILLEGAL_PARAMETER, ERR_MSG).toJSON();
}
String date = dateStr.substring(0, 10);
String time = dateStr.substring(11);
System.err.println("date:"+date+"; time:"+time+";spaceId:"+spaceId);
log.info("date:{}; time:{};spaceId:{}", date, time, spaceId);
List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findAllListByDate(date,time, spaceId);
List<DmMeetingOrdersDto> res = new ArrayList<>();
list.forEach(item -> {
@@ -427,19 +436,19 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
/*
* 获取会议室最近的可用时间段
* @Author yangkai
* @Description //TODO
* @Description
* @Date 2023/9/1
* @Param [roomId, objects, currentTime]
* @return java.util.List
**/
List freeTimePart (Long roomId, List<DmMeetingOrdersPo> objects, String currentTime) {
public List<JSONObject> freeTimePart (Long roomId, List<DmMeetingOrdersPo> objects, String currentTime) {
List<JSONObject> freeTimeList = new ArrayList<>();

if (null == objects || objects.size() ==0) {
if (null == objects || objects.isEmpty()) {
JSONObject json = new JSONObject();
json.put("startTime", currentTime);
json.put("endTime", 0);
json.put("roomId", roomId);
json.put(START_TIME_KEY, currentTime);
json.put(END_TIME_KEY, 0);
json.put(ROOM_ID_KEY, roomId);
freeTimeList.add(json);
return freeTimeList;
}
@@ -447,30 +456,29 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
DmMeetingOrdersPo current = objects.get(0);
if (MyDateUtils.formatDate(current.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(currentTime) > 0 ) {
JSONObject json = new JSONObject();
json.put("startTime", currentTime);
json.put("endTime", MyDateUtils.formatDate(current.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put("roomId", roomId);
json.put(START_TIME_KEY, currentTime);
json.put(END_TIME_KEY, MyDateUtils.formatDate(current.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put(ROOM_ID_KEY, roomId);
freeTimeList.add(json);
} else {
if (MyDateUtils.formatDate(current.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(currentTime) > 0 ) {
JSONObject json = new JSONObject();
json.put("startTime", MyDateUtils.formatDate(current.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put("endTime", 0);
json.put("roomId", roomId);
json.put(START_TIME_KEY, MyDateUtils.formatDate(current.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put(END_TIME_KEY, 0);
json.put(ROOM_ID_KEY, roomId);
freeTimeList.add(json);
} else {
JSONObject json = new JSONObject();
json.put("startTime", currentTime);
json.put("endTime", 0);
json.put("roomId", roomId);
json.put(START_TIME_KEY, currentTime);
json.put(END_TIME_KEY, 0);
json.put(ROOM_ID_KEY, roomId);
freeTimeList.add(json);
}

}
return freeTimeList;
}
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern(MyDateUtils.DEFAULT_TIME_PATTERN);
objects = objects.stream().sorted(Comparator.comparing(po -> MyDateUtils.formatDate(po.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN))).collect(Collectors.toList());
objects = objects.stream().sorted(Comparator.comparing(po -> MyDateUtils.formatDate(po.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN))).toList();
for (int i = 0; i < objects.size() - 1; i++) {
DmMeetingOrdersPo current = objects.get(i);
DmMeetingOrdersPo next = objects.get(i + 1);
@@ -485,12 +493,12 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
if (i==objects.size() - 2) {
JSONObject json = new JSONObject();
if (MyDateUtils.formatDate(next.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(currentTime)>0) {
json.put("startTime", MyDateUtils.formatDate(next.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put(START_TIME_KEY, MyDateUtils.formatDate(next.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
} else {
json.put("startTime", currentTime);
json.put(START_TIME_KEY, currentTime);
}
json.put("endTime", 0);
json.put("roomId", current.getSpaceId());
json.put(END_TIME_KEY, 0);
json.put(ROOM_ID_KEY, current.getSpaceId());
freeTimeList.add(json);
}
continue;
@@ -498,29 +506,29 @@ public class DmMeetingInnerApiController extends MyBaseApiController {

if (i==0 && MyDateUtils.formatDate(current.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(currentTime) > 0 ) {
JSONObject json = new JSONObject();
json.put("startTime", currentTime);
json.put("endTime", MyDateUtils.formatDate(current.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put("roomId", roomId);
json.put(START_TIME_KEY, currentTime);
json.put(END_TIME_KEY, MyDateUtils.formatDate(current.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put(ROOM_ID_KEY, roomId);
freeTimeList.add(json);
}

if (freeStartTime.before(freeEndTime)) {
JSONObject json = new JSONObject();
json.put("startTime", freeStartTimeStr);
json.put("endTime", freeEndTimeStr);
json.put("roomId", roomId);
json.put(START_TIME_KEY, freeStartTimeStr);
json.put(END_TIME_KEY, freeEndTimeStr);
json.put(ROOM_ID_KEY, roomId);
freeTimeList.add(json);
}

if (i==objects.size() - 2) {
JSONObject json = new JSONObject();
if (MyDateUtils.formatDate(next.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(currentTime)>0) {
json.put("startTime", MyDateUtils.formatDate(next.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
json.put(START_TIME_KEY, MyDateUtils.formatDate(next.getEndTime(), MyDateUtils.DEFAULT_TIME_PATTERN));
} else {
json.put("startTime", currentTime);
json.put(START_TIME_KEY, currentTime);
}
json.put("endTime", 0);
json.put("roomId", current.getSpaceId());
json.put(END_TIME_KEY, 0);
json.put(ROOM_ID_KEY, current.getSpaceId());
freeTimeList.add(json);
}
}
@@ -547,26 +555,26 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
}
Map<Long, String> finalRooms = rooms;
Map<Long, Integer> finalSorts = sorts;
arr = arr.stream().map(j->{j.put("roomName", finalRooms.get(j.getLong("roomId")));j.put("sort", finalSorts.get(j.getLong("roomId")));return j;}).sorted(Comparator.comparing(po -> po.getString("startTime"))).collect(Collectors.toList());
arr = arr.stream().map(j->{j.put("roomName", finalRooms.get(j.getLong(ROOM_ID_KEY)));j.put("sort", finalSorts.get(j.getLong(ROOM_ID_KEY)));return j;}).sorted(Comparator.comparing(po -> po.getString(START_TIME_KEY))).toList();
List<JSONObject> arr2 = new ArrayList<>();
for (int i=0;i<arr.size();i++){
JSONObject j = arr.get(i);
if (arr2.size() == 0 || arr2.get(0).getString("startTime").equals(j.getString("startTime"))) {
if (arr2.isEmpty() || arr2.get(0).getString(START_TIME_KEY).equals(j.getString(START_TIME_KEY))) {
arr2.add(j);
} else {
break;
}
}

return arr2.size()>0 ? arr2.stream().sorted(Comparator.comparing(po -> po.getInteger("sort"))).collect(Collectors.toList()).get(0) : null;
return !arr2.isEmpty() ? arr2.stream().sorted(Comparator.comparing(po -> po.getInteger("sort"))).toList().get(0) : null;
}

@InnerAuth
@GetMapping("/recent/{deptId}/{dateStr}")
@ResponseBody
public List<JSONObject> recent(@PathVariable(value = "deptId") Long deptId,@PathVariable(value = "dateStr") String dateStr,@RequestParam(value = "roomId", required = false) Long roomId,@RequestParam(value = "startTime", required = false) String startTime, HttpServletRequest request) {
public List<JSONObject> recent(@PathVariable(value = "deptId") Long deptId,@PathVariable(value = "dateStr") String dateStr,@RequestParam(value = ROOM_ID_KEY, required = false) Long roomId,@RequestParam(value = START_TIME_KEY, required = false) String startTime, HttpServletRequest request) {

List<DmMeetingOrdersPo> list = new ArrayList<>();
List<DmMeetingOrdersPo> list ;
List<Long> ids = new ArrayList<>();
Map<Long, String> rooms = new HashMap<>();
if (null == roomId) {
@@ -585,7 +593,7 @@ public class DmMeetingInnerApiController extends MyBaseApiController {


//过滤掉今天的已经过去的预约记录,并按开始时间进行排序
list = list.stream().filter(t-> MyDateUtils.formatDate(t.getOrderDate(), MyDateUtils.DEFAULT_DATE_PATTERN).compareTo(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN))>0 || (MyDateUtils.formatDate(t.getOrderDate(), MyDateUtils.DEFAULT_DATE_PATTERN).compareTo(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN))==0 && MyDateUtils.formatDate(t.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_TIME_PATTERN))>0)).sorted(Comparator.comparing(po -> MyDateUtils.formatDate(po.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN))).collect(Collectors.toList());
list = list.stream().filter(t-> MyDateUtils.formatDate(t.getOrderDate(), MyDateUtils.DEFAULT_DATE_PATTERN).compareTo(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN))>0 || (MyDateUtils.formatDate(t.getOrderDate(), MyDateUtils.DEFAULT_DATE_PATTERN).compareTo(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN))==0 && MyDateUtils.formatDate(t.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_TIME_PATTERN))>0)).sorted(Comparator.comparing(po -> MyDateUtils.formatDate(po.getStartTime(), MyDateUtils.DEFAULT_TIME_PATTERN))).toList();


//获得当前时间开始最近的整点,或者半点
@@ -618,11 +626,10 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
List<JSONObject> arr = new ArrayList<>();
for (int i=0;i<freeTime.keySet().size();i++){
Long key = (Long) freeTime.keySet().toArray()[i];
List<JSONObject> value = freeTime.get(key);
arr.addAll(freeTime.get(key));
}
Map<Long, String> finalRooms = rooms;
arr = arr.stream().map(j->{j.put("roomName", finalRooms.get(j.getLong("roomId")));return j;}).sorted(Comparator.comparing(po -> po.getString("startTime"))).collect(Collectors.toList());
arr = arr.stream().map(j->{j.put("roomName", finalRooms.get(j.getLong(ROOM_ID_KEY)));return j;}).sorted(Comparator.comparing(po -> po.getString(START_TIME_KEY))).collect(Collectors.toList());
return arr;
}

@@ -634,10 +641,9 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
@ResponseBody
public List<JSONObject> recent(@PathVariable(value = "deptId") Long deptId) {

List<DmMeetingOrdersPo> list = new ArrayList<>();
List<Long> ids = new ArrayList<>();
Map<Long, String> rooms = new HashMap<>();
Map<Long, Integer> sorts = new HashMap<>();
List<Long> ids;
Map<Long, String> rooms;
Map<Long, Integer> sorts;
//当天
String dateStr = MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN);

@@ -645,10 +651,10 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
dm.setDeptId(deptId);
List<DmMeetingRoomsPo> pos = dmMeetingRoomsMapper.selectRoomList(dm);

ids = pos.stream().map(DmMeetingRoomsPo::getId).collect(Collectors.toList());
ids = pos.stream().map(DmMeetingRoomsPo::getId).toList();
rooms = pos.stream().collect(Collectors.toMap(DmMeetingRoomsPo::getId, DmMeetingRoomsPo::getName));
sorts = pos.stream().collect(Collectors.toMap(DmMeetingRoomsPo::getId, DmMeetingRoomsPo::getSort));
log.info("ids:" + ids);
log.info("ids:{}" , ids);

//获得当前时间开始最近的整点,或者半点
String currentStr = "08:00";
@@ -666,8 +672,8 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
String nextDateStr = MyDateUtils.dateStrAdd(dateStr, 1);
Map<Long, List<DmMeetingOrdersPo>> nextGroupedByRoom = ordersService.selectOrderedList(deptId,nextDateStr);
JSONObject js1 = getList(currentStr, groupedByRoom, rooms, sorts, ids);
JSONObject js2 = new JSONObject();
JSONObject js3 = new JSONObject();
JSONObject js2 ;
JSONObject js3 ;
if (MyDateUtils.isAmPm().equals("am")) {
currentStr = "14:00";
js2 = getList(currentStr, groupedByRoom, rooms, sorts, ids);
@@ -682,19 +688,19 @@ public class DmMeetingInnerApiController extends MyBaseApiController {
}
List<JSONObject> arr = new ArrayList<>();
if (ObjectUtil.isNotEmpty(js1)) {
js1.put("orderDate", dateStr);
js1.put(ORDER_DATE_KEY, dateStr);
arr.add(js1);
}
if (ObjectUtil.isNotEmpty(js2)) {
if (MyDateUtils.isAmPm().equals("am")) {
js2.put("orderDate", dateStr);
js2.put(ORDER_DATE_KEY, dateStr);
} else {
js2.put("orderDate", nextDateStr);
js2.put(ORDER_DATE_KEY, nextDateStr);
}
arr.add(js2);
}
if (ObjectUtil.isNotEmpty(js3)) {
js3.put("orderDate", nextDateStr);
js3.put(ORDER_DATE_KEY, nextDateStr);
arr.add(js3);
}



+ 0
- 1
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/mapper/DmMeetingRoomsMapper.java 파일 보기

@@ -1,6 +1,5 @@
package com.xueyi.system.meeting.mapper;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.xueyi.common.datasource.annotation.Isolate;
import com.xueyi.common.web.annotation.TenantIgnore;
import com.xueyi.common.web.entity.mapper.BaseMapper;


+ 0
- 1
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/service/impl/DmMeetingOrdersServiceImpl.java 파일 보기

@@ -14,7 +14,6 @@ import com.xueyi.system.staff.service.impl.DmStaffServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;


+ 18
- 14
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/pass/controller/api/DmRecognizedRecordsInnerApiController.java 파일 보기

@@ -13,6 +13,7 @@ import com.xueyi.common.web.response.MyResponse;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.file.api.domain.SysFile;
import com.xueyi.file.api.feign.RemoteFileService;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.api.pass.domain.dto.DmRecognizedMultiRecordsDto;
import com.xueyi.system.api.pass.domain.dto.DmRecognizedRecordsDto;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
@@ -25,9 +26,12 @@ import com.xueyi.system.resource.domain.dto.DmResourcesDto;
import com.xueyi.system.resource.service.impl.DmResourcesServiceImpl;
import com.xueyi.system.resource.service.impl.FaceServiceImpl;
import com.xueyi.system.staff.mapper.DmStaffMapper;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import com.xueyi.system.staff.service.impl.DmStaffServiceImpl;
import com.xueyi.system.utils.common.ImageUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -48,6 +52,8 @@ import java.util.List;
@RequestMapping("/pass/inner-api")
public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {

Logger logger = LoggerFactory.getLogger(FaceServiceImpl.class);

@Autowired
private DmStaffMapper dmStaffMapper;

@@ -77,6 +83,9 @@ public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {

@Autowired
private ElasticsearchClient esClient;

@Autowired
private DmVisitorsMapper visitorsMapper;
@InnerAuth
@PostMapping(value = "/upload-pass")
public JSONObject upload(@RequestBody DmRecognizedRecordsDto recognizedRecordsDto) {
@@ -108,10 +117,15 @@ public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {

dmStaffService.updateOrInsertAttendance(cr);
}
} else {
DmVisitorsPo visitorsPo = visitorsMapper.selectById(userId);
if (ObjectUtils.anyNotNull(visitorsPo)) {
cr.setUserName(visitorsPo.getName());
}
}

if (StringUtils.isNotEmpty(imgBase64)) {
R<SysFile> fileResult = fileService.uploadTemp(imageUtil.convertToMultipartFile(imgBase64));
R<SysFile> fileResult = fileService.uploadTemp(ImageUtil.convertToMultipartFile(imgBase64));
if (ObjectUtil.isNull(fileResult) || ObjectUtil.isNull(fileResult.getData()))
return output(ResponseCode.FILE_SERVICE_ERROR).toJSON();
String url = fileResult.getData().getUrl();
@@ -119,7 +133,7 @@ public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {
}

dmRecognizedRecordsMapper.insert(cr);
recognizedRecordsService.saveToEs(recordsConverter.mapperDto(cr));
// recognizedRecordsService.saveToEs(recordsConverter.mapperDto(cr));//

recognizedRecordsService.setRedisRecognizedCount(1);

@@ -132,6 +146,7 @@ public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {
String deviceId = recognizedMultiRecordsDto.getDevId();
BigDecimal timestamp = recognizedMultiRecordsDto.getTimestamp();
String sign = recognizedMultiRecordsDto.getSign();
logger.info("recognizedMultiRecordsDto :{}",recognizedMultiRecordsDto);

MyResponse myResponse = commonCheck(deviceId, timestamp.doubleValue(), sign);
if (myResponse.getStatus() != 0) {
@@ -163,7 +178,7 @@ public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {
}
}
if (StringUtils.isNotEmpty(imgBase64)) {
R<SysFile> fileResult = fileService.uploadTemp(imageUtil.convertToMultipartFile(imgBase64));
R<SysFile> fileResult = fileService.uploadTemp(ImageUtil.convertToMultipartFile(imgBase64));
if (ObjectUtil.isNull(fileResult) || ObjectUtil.isNull(fileResult.getData()))
return output(ResponseCode.FILE_SERVICE_ERROR).toJSON();
String url = fileResult.getData().getUrl();
@@ -172,22 +187,11 @@ public class DmRecognizedRecordsInnerApiController extends MyBaseApiController {
dmResourcesDto.setUrl(url);
dmResourcesDto.setName("stranger");

/**
com.alibaba.fastjson.JSONObject json = faceService.getFaceExtraction("", "", imgBase64);

if (0!=json.getInteger("status")) {
return output(-1, json.getString("errMsg")).toJSON();
} else {
JSONArray obj = json.getJSONArray("result").getJSONObject(0).getJSONArray("faces").getJSONObject(0).getJSONArray("feature");
dmResourcesDto.setFeature(obj.toJSONString());
}*/

iDmResourcesService.addOne(dmResourcesDto);
cr.setFaceUrl(url);
cr.setId(IdUtil.getSnowflakeNextId());
cr.setResourceId(dmResourcesDto.getId());
}
// recognizedRecordsService.saveToEs(recordsConverter.mapperDto(cr));
crs.add(cr);
}



+ 2
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/resource/mapper/DmResourcesMapper.java 파일 보기

@@ -14,4 +14,6 @@ import com.xueyi.common.datasource.annotation.Isolate;
@Isolate
public interface DmResourcesMapper extends BaseMapper<DmResourcesQuery, DmResourcesDto, DmResourcesPo> {
Long insertOne(DmResourcesPo dmResourcesPo);


}

+ 22
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/resource/service/impl/DmResourcesServiceImpl.java 파일 보기

@@ -89,4 +89,26 @@ public class DmResourcesServiceImpl extends BaseServiceImpl<DmResourcesQuery, Dm
}
return R.ok(dmResourcesDto);
}

public R<DmResourcesDto> saveVisitorBase64Image(String base64Image, String visitorName){
R<SysFile> fileResult = fileService.uploadFace(ImageUtil.convertToMultipartFile(base64Image));
if (ObjectUtil.isNull(fileResult) || ObjectUtil.isNull(fileResult.getData()))
return R.fail("文件服务异常");
String url = fileResult.getData().getUrl();
DmResourcesDto dmResourcesDto = new DmResourcesDto();
dmResourcesDto.setType(DmResourcesDto.TYPE_PIC);
dmResourcesDto.setUrl(url);
dmResourcesDto.setName("visitor-"+visitorName);

com.alibaba.fastjson.JSONObject json = faceService.getFaceExtraction("", "", base64Image);

if (0!=json.getInteger("status")) {
return R.fail(json.getString("errMsg"));
} else {
JSONArray obj = json.getJSONArray("result").getJSONObject(0).getJSONArray("faces").getJSONObject(0).getJSONArray("feature");
dmResourcesDto.setFeature(obj.toJSONString());
}
addOne(dmResourcesDto);
return R.ok(dmResourcesDto);
}
}

+ 13
- 8
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/resource/service/impl/FaceServiceImpl.java 파일 보기

@@ -4,11 +4,14 @@ package com.xueyi.system.resource.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xueyi.file.api.feign.RemoteFileService;
import com.xueyi.system.utils.common.ImageUtil;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
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.HttpEntity;
@@ -27,6 +30,7 @@ import java.util.Map;
@Slf4j
@Component
public class FaceServiceImpl {
private static Logger logger = LoggerFactory.getLogger(FaceServiceImpl.class);

@Value("${face.server}")
private String faceServer;
@@ -51,6 +55,9 @@ public class FaceServiceImpl {
@Autowired
private RestTemplate restTemplate;

@Autowired
private RemoteFileService fileService;


public static String execCurl(String[] cmds) {
ProcessBuilder process = new ProcessBuilder(cmds);
@@ -67,7 +74,7 @@ public class FaceServiceImpl {
return builder.toString();

} catch (IOException e) {
System.out.print("error");
logger.info("error");
e.printStackTrace();
}
return null;
@@ -122,7 +129,7 @@ public class FaceServiceImpl {
String path = faceServer;

String result = restTemplate.postForObject(path + extractionPath, entity, String.class, "face-detection");
System.err.println(path + extractionPath);
logger.info(path + extractionPath);
JSONObject resultJson = JSON.parseObject(result);

return resultJson;
@@ -136,7 +143,7 @@ public class FaceServiceImpl {

/********restTemplate 请求方式*************/
try {
imgBase64 = imgBase64.replaceAll("data:image/jpeg;base64,", "");
imgBase64 = imgBase64.replace("data:image/jpeg;base64,", "");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer "+token);
@@ -150,7 +157,7 @@ public class FaceServiceImpl {
map.add("detect", true);
map.add("images", jsonArray);
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(map.toSingleValueMap(), headers);
System.err.println(faceServer + qualityPath);
logger.info(faceServer + qualityPath);
String result = restTemplate.postForObject(faceServer + qualityPath, entity, String.class, "face-detection");


@@ -158,7 +165,6 @@ public class FaceServiceImpl {

return resultJson.getJSONArray("result").getJSONObject(0);
} catch (Exception e) {
System.err.println("8888err");
e.printStackTrace();
throw e;
}
@@ -172,7 +178,7 @@ public class FaceServiceImpl {
JSONObject json = new JSONObject();

try {
imgBase64 = imgBase64.replaceAll("data:image/jpeg;base64,", "");
imgBase64 = imgBase64.replace("data:image/jpeg;base64,", "");
JSONObject res = this.getFaceExtraction(token, imageId, imgBase64);

JSONObject obj = res.getJSONArray("faces").getJSONObject(0);
@@ -204,7 +210,7 @@ public class FaceServiceImpl {
JSONObject json = new JSONObject();

try {
imgBase64 = imgBase64.replaceAll("data:image/jpeg;base64,", "");
imgBase64 = imgBase64.replace("data:image/jpeg;base64,", "");
JSONObject res = this.getFaceCheck(token, imageId, imgBase64);

Boolean passed = res.getBoolean("passed");
@@ -289,5 +295,4 @@ public class FaceServiceImpl {
json.put("feature",array.toJSONString());
return json;
}

}

+ 13
- 5
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/DmStaffController.java 파일 보기

@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import com.xueyi.common.core.utils.file.FileTypeUtil;
@@ -35,6 +36,8 @@ import com.xueyi.system.api.staff.domain.vo.DmStaffFeature;
import com.xueyi.system.staff.service.IDmStaffService;
import com.xueyi.tenant.api.tenant.domain.po.SysEnterpriseStaff;
import com.xueyi.tenant.api.tenant.feign.RemoteTenantService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -53,6 +56,7 @@ import java.util.List;
@RestController
@RequestMapping("/staff")
public class DmStaffController extends BaseController<DmStaffQuery, DmStaffDto, IDmStaffService> {
private static final Logger logger = LoggerFactory.getLogger(DmStaffController.class);

@Autowired
IDmStaffService dmStaffService;
@@ -140,12 +144,16 @@ public class DmStaffController extends BaseController<DmStaffQuery, DmStaffDto,
if (dto != null) {
dmStaff.setAvatar(dto.getUrl());
}
SysEnterpriseStaff enterpriseStaff = new SysEnterpriseStaff();
enterpriseStaff.setPhone(dmStaff.getPhone());
enterpriseStaff.setStaffId(dmStaff.getId());
enterpriseStaff.setTId(SecurityContextHolder.getEnterpriseId());
tenantService.saveEnterpriseStaff(enterpriseStaff, SecurityConstants.INNER);
}
long id = IdUtil.getSnowflakeNextId();
dmStaff.setId(id);
//以下代码添加主库企业和员工的关系映射表,用于手机号登录以及小程序登录
SysEnterpriseStaff enterpriseStaff = new SysEnterpriseStaff();
enterpriseStaff.setPhone(dmStaff.getPhone());
enterpriseStaff.setStaffId(id);
enterpriseStaff.setId(id);
enterpriseStaff.setTId(SecurityContextHolder.getEnterpriseId());
tenantService.saveEnterpriseStaff(enterpriseStaff, SecurityConstants.INNER);
AjaxResult result = super.add(dmStaff);
if (dmStaff.getBirthDate() != null) {
DmWebSocketMessageVo vo = new DmWebSocketMessageVo();


+ 28
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/DmVisitorSmsConfigController.java 파일 보기

@@ -1,15 +1,19 @@
package com.xueyi.system.staff.controller;

import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.core.web.validate.V_A;
import com.xueyi.common.core.web.validate.V_E;
import com.xueyi.common.log.annotation.Log;
import com.xueyi.common.log.enums.BusinessType;
import com.xueyi.common.security.annotation.RequiresPermissions;
import com.xueyi.common.web.entity.controller.BaseController;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitRecordsPo;
import com.xueyi.system.staff.domain.dto.DmVisitorSmsConfigDto;
import com.xueyi.system.staff.domain.query.DmVisitorSmsConfigQuery;
import com.xueyi.system.staff.mapper.DmVisitRecordsMapper;
import com.xueyi.system.staff.service.IDmVisitorSmsConfigService;
import com.xueyi.system.staff.service.impl.DmVisitRecordsServiceImpl;
import com.xueyi.system.staff.service.impl.DmVisitorSmsConfigServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
@@ -20,6 +24,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.Serializable;
@@ -37,6 +42,14 @@ public class DmVisitorSmsConfigController extends BaseController<DmVisitorSmsCon
@Autowired
private DmVisitorSmsConfigServiceImpl visitorSmsConfigService;

@Autowired
private DmVisitRecordsServiceImpl visitRecordsService;

@Autowired
private DmVisitRecordsMapper visitRecordsMapper;



/** 定义节点名称 */
@Override
protected String getNodeName() {
@@ -105,6 +118,21 @@ public class DmVisitorSmsConfigController extends BaseController<DmVisitorSmsCon
return super.batchRemove(idList);
}


@GetMapping("/send-sms")
public AjaxResult sendVisitorSms(@RequestParam("visitRecordId") Long visitRecordId, @RequestParam(value = "staffId", required = false) Long staffId) {
if (null != visitRecordId) {
DmVisitRecordsPo po = visitRecordsMapper.selectById(visitRecordId);
R<String> r = visitRecordsService.sendSms(po);
if (r.isOk()) {
return AjaxResult.success("短信发送成功,请注意查收");
} else {
return AjaxResult.error(r.getMsg());
}
}
return AjaxResult.success("短信发送成功,请注意查收");
}

/**
* 获取租户访客接待短信模板配置选择框列表
*/


+ 0
- 15
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/api/DmStaffInnerApiController.java 파일 보기

@@ -7,7 +7,6 @@ import com.xueyi.common.core.constant.basic.SqlConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.security.annotation.InnerAuth;
import com.xueyi.common.web.constant.ResponseCode;
import com.xueyi.file.api.feign.RemoteFileService;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.api.staff.domain.dto.DmStaffCommonDto;
@@ -15,11 +14,9 @@ import com.xueyi.system.api.staff.domain.po.DmStaffPo;
import com.xueyi.system.resource.controller.api.MyBaseApiController;
import com.xueyi.system.resource.domain.dto.DmResourcesDto;
import com.xueyi.system.resource.service.impl.DmResourcesServiceImpl;
import com.xueyi.system.resource.service.impl.FaceServiceImpl;
import com.xueyi.system.staff.mapper.DmStaffMapper;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import com.xueyi.system.staff.service.impl.DmStaffServiceImpl;
import com.xueyi.system.utils.common.ImageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -42,24 +39,12 @@ public class DmStaffInnerApiController extends MyBaseApiController {
@Autowired
private DmStaffMapper dmStaffMapper;

@Autowired
private RemoteFileService fileService;

@Autowired
private FaceServiceImpl faceService;

@Autowired
private ImageUtil imageUtil;

@Autowired
private DmResourcesServiceImpl iDmResourcesService;

@Autowired
private DmVisitorsMapper dmVisitorsMapper;

@Autowired
private DmStaffMapper staffMapper;

@Autowired
private DmStaffServiceImpl dmStaffService;



+ 8
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/api/DmVisitorApiController.java 파일 보기

@@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@@ -68,6 +69,13 @@ public class DmVisitorApiController extends MyBaseApiController {

}

@GetMapping(value = "visitors")
@ResponseBody
public JSONObject visitors(@RequestParam("devId") String devId){
DeviceTenantSourceMergeVo vo = super.getDeviceTenantSourceMergeVo(devId);
return visitorService.visitors(vo.getTenantId(), vo.getSourceSlave(), SecurityConstants.INNER);
}

@PostMapping(value = "new-visitor")
@ResponseBody
public JSONObject newVisit(@RequestBody DmVisitCommonDto commonDto){


+ 57
- 117
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/controller/api/DmVisitorInnerApiController.java 파일 보기

@@ -1,11 +1,9 @@
package com.xueyi.system.staff.controller.api;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xueyi.common.cache.utils.DictUtil;
@@ -16,12 +14,9 @@ import com.xueyi.common.security.annotation.InnerAuth;
import com.xueyi.common.sms.configure.SmsProperties;
import com.xueyi.common.web.constant.ResponseCode;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.file.api.domain.SysFile;
import com.xueyi.file.api.feign.RemoteFileService;
import com.xueyi.system.api.dict.domain.dto.SysDictDataDto;
import com.xueyi.system.api.dict.domain.po.SysDictDataPo;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitRecordsDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitRecordsPo;
@@ -32,22 +27,20 @@ import com.xueyi.system.api.staff.domain.dto.DmVisitCommonDto;
import com.xueyi.system.api.staff.domain.po.DmStaffPo;
import com.xueyi.system.digitalmans.mapper.DmDigitalmanExtMapper;
import com.xueyi.system.digitalmans.mapper.DmDigitalmanMapper;
import com.xueyi.system.meeting.constant.VisitRecordStatus;
import com.xueyi.system.receiver.domain.po.DmTenantReceiverPo;
import com.xueyi.system.receiver.mapper.DmTenantReceiverMapper;
import com.xueyi.system.resource.controller.api.MyBaseApiController;
import com.xueyi.system.resource.domain.dto.DmResourcesDto;
import com.xueyi.system.resource.service.impl.DmResourcesServiceImpl;
import com.xueyi.system.resource.service.impl.FaceServiceImpl;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.model.DmVisitRecordsConverter;
import com.xueyi.system.staff.domain.model.DmVisitorSmsConfigConverter;
import com.xueyi.system.staff.domain.po.DmVisitorSmsConfigPo;
import com.xueyi.system.staff.mapper.DmStaffMapper;
import com.xueyi.system.staff.mapper.DmVisitRecordsMapper;
import com.xueyi.system.staff.mapper.DmVisitorSmsConfigMapper;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import com.xueyi.system.staff.service.impl.DmVisitRecordsServiceImpl;
import com.xueyi.system.utils.common.ImageUtil;
import com.xueyi.system.staff.service.impl.DmVisitorOperateLogServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -61,7 +54,6 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
* 访客管理 API业务处理
@@ -91,10 +83,6 @@ public class DmVisitorInnerApiController extends MyBaseApiController {
@Autowired
private DmVisitRecordsConverter recordsConverter;

@Autowired
private DmVisitorSmsConfigConverter visitorSmsConfigConverter;


@Autowired
private DmVisitorSmsConfigMapper visitorSmsConfigMapper;

@@ -104,20 +92,14 @@ public class DmVisitorInnerApiController extends MyBaseApiController {
@Autowired
DmTenantReceiverMapper receiverMapper;

@Autowired
private RemoteFileService fileService;

@Autowired
private FaceServiceImpl faceService;

@Autowired
private DmResourcesServiceImpl iDmResourcesService;

@Autowired
private ImageUtil imageUtil;
private StringRedisTemplate redisTemplate;

@Autowired
private StringRedisTemplate redisTemplate;
private DmVisitorOperateLogServiceImpl visitorOperateLogService;

@InnerAuth
@PostMapping(value = "confirm-visitor")
@@ -136,7 +118,6 @@ public class DmVisitorInnerApiController extends MyBaseApiController {
json.put("visitorName", visitorsPo.getName());
}

// DmStaffPo e = dmStaffMapper.selectById(v.getUserId());
if (v.getReceiverPhone() != null){
json.put("phone", v.getReceiverPhone());
json.put("visitorId", v.getVisitorId());
@@ -163,106 +144,61 @@ public class DmVisitorInnerApiController extends MyBaseApiController {
@InnerAuth
@PostMapping(value = "new-visitor")
public com.alibaba.fastjson2.JSONObject newVisit(@RequestBody DmVisitCommonDto commonDto){
DmVisitRecordsPo visitRecords = visitRecordsService.initVisitRecord(commonDto);
if (visitRecords == null) {
return output(ResponseCode.DATA_NOT_EXISTS, "员工").toJSON();
}
DmVisitorsPo v = null;
if (StringUtils.isNotEmpty(commonDto.getVisitorTel())) {
v = dmVisitorsMapper.selectOne(
Wrappers.<DmVisitorsPo>query().lambda()
.eq(DmVisitorsPo::getPhone, commonDto.getVisitorTel()).last(SqlConstants.LIMIT_ONE));
if (commonDto.getVisitorId() == null) {//新的访客
if (StringUtils.isNotEmpty(commonDto.getVisitorTel())) {
v = dmVisitorsMapper.selectOne(
Wrappers.<DmVisitorsPo>query().lambda()
.eq(DmVisitorsPo::getPhone, commonDto.getVisitorTel()).last(SqlConstants.LIMIT_ONE));
}
} else {//旧的访客
v = dmVisitorsMapper.selectById(commonDto.getVisitorId());
}
if (v == null) {
v = new DmVisitorsPo();
v.setName(commonDto.getVisitorName());
v.setNickname(commonDto.getVisitorNickName());
v.setVisitorCompany(commonDto.getVisitCompany());
v.setPhone(commonDto.getVisitorTel());
v.setType(DmVisitorsDto.TYPE_NORMAL_VISITOR);

List<DmVisitorOperateLogDto> operateLogs = new ArrayList<>();
if (v == null) {//后台无访客数据,新建访客
v = visitRecordsService.initVisitor(commonDto);
//兼容熟人介绍生人,传递访客照片
if (StringUtils.isNotEmpty(commonDto.getVisitorBase64Img())) {
String imgBase64 = commonDto.getVisitorBase64Img();
R<SysFile> fileResult = fileService.uploadFace(imageUtil.convertToMultipartFile(imgBase64));
if (ObjectUtil.isNull(fileResult) || ObjectUtil.isNull(fileResult.getData()))
return output(ResponseCode.FILE_SERVICE_ERROR).toJSON();
String url = fileResult.getData().getUrl();
DmResourcesDto dmResourcesDto = new DmResourcesDto();
dmResourcesDto.setType(DmResourcesDto.TYPE_PIC);
dmResourcesDto.setUrl(url);
dmResourcesDto.setName("stranger");

com.alibaba.fastjson.JSONObject json = faceService.getFaceExtraction("", "", imgBase64);

if (0!=json.getInteger("status")) {
return output(-1, json.getString("errMsg")).toJSON();
} else {
JSONArray obj = json.getJSONArray("result").getJSONObject(0).getJSONArray("faces").getJSONObject(0).getJSONArray("feature");
dmResourcesDto.setFeature(obj.toJSONString());
R<DmResourcesDto> resourcesDtoR = iDmResourcesService.saveVisitorBase64Image(imgBase64, commonDto.getVisitorName());
if (resourcesDtoR.isOk()){
DmResourcesDto dmResourcesDto = resourcesDtoR.getData();
v.setAvatar(dmResourcesDto.getUrl());
v.setResourceId(dmResourcesDto.getId());
}

iDmResourcesService.addOne(dmResourcesDto);
v.setAvatar(dmResourcesDto.getUrl());
v.setResourceId(dmResourcesDto.getId());
}
dmVisitorsMapper.addOne(v);
} else {
Long res = dmVisitorsMapper.addOne(v);
DmVisitorOperateLogDto visitorOperateLogPo = visitorOperateLogService.initData(v.getId(), commonDto.getEmpId(), DmVisitorOperateLogDto.BUSINESS_TYPE_CREATE, "createVisitor", JSON.toJSONString(commonDto), JSON.toJSONString(res));
operateLogs.add(visitorOperateLogPo);
} else {//后台有访客数据,更新访客信息
v.setName(commonDto.getVisitorName());
v.setNickname(commonDto.getVisitorNickName());
v.setPhone(commonDto.getVisitorTel());
v.setVisitorCompany(commonDto.getVisitCompany());
dmVisitorsMapper.updateById(v);
Integer res = dmVisitorsMapper.updateById(v);
DmVisitorOperateLogDto visitorOperateLogPo = visitorOperateLogService.initData(v.getId(), commonDto.getEmpId(), DmVisitorOperateLogDto.BUSINESS_TYPE_UPDATE, "updateVisitor", JSON.toJSONString(commonDto), JSON.toJSONString(res));
operateLogs.add(visitorOperateLogPo);
}
DmVisitRecordsPo visitRecords = new DmVisitRecordsPo();
try {
DmStaffPo emp = dmStaffMapper.selectOne(
Wrappers.<DmStaffPo>query().lambda()
.eq(DmStaffPo::getId, commonDto.getEmpId()).last(SqlConstants.LIMIT_ONE));
if (ObjectUtils.isNotEmpty(emp)) {
visitRecords.setDeptId(emp.getDeptId());
visitRecords.setVisitorId(v.getId());
if (StringUtils.isNotEmpty(commonDto.getVisitDate())) {
visitRecords.setVisitDate(LocalDateTimeUtil.of(MyDateUtils.parseStrToDate(commonDto.getVisitDate(), MyDateUtils.DEFAULT_DATE_PATTERN)).toLocalDate());
}
visitRecords.setUserId(commonDto.getEmpId());
visitRecords.setRecordStatus(VisitRecordStatus.getRecordStatusStart());
String code = visitRecordsService.genVisitorCode();
visitRecords.setVisitorCode(code);
visitRecords.setReceiverName(commonDto.getEmpName());
visitRecords.setReceiverPhone(commonDto.getEmpTel());
dmVisitRecordsMapper.insert(visitRecords);
redisTemplate.opsForValue().increment("dashboard:create_visitor_info", 1);
JSONObject json = new JSONObject();
if (null != commonDto.getVisitorTel()){

DmVisitorSmsConfigPo dmVisitorSmsConfigPo = visitorSmsConfigMapper.selectOne(Wrappers.<DmVisitorSmsConfigPo>query().lambda().last(SqlConstants.LIMIT_ONE));

DmDigitalmanPo dmDigitalmanPo = digitalmanMapper.selectByCode(digitalmanExtMapper.selectOne(Wrappers.<DmDigitalmanExtPo>query().lambda().eq(DmDigitalmanExtPo::getDeviceId, commonDto.getDevId()).last(SqlConstants.LIMIT_ONE)).getManCode());

json.put("code", code);
json.put("nickName", commonDto.getVisitorName());
json.put("robotName", dmDigitalmanPo.getName());
json.put("dateTime", commonDto.getVisitDate());
json.put("companyName", dmVisitorSmsConfigPo!=null?dmVisitorSmsConfigPo.getCompanyName():"");
json.put("companyAddr", dmVisitorSmsConfigPo!=null?dmVisitorSmsConfigPo.getCompanyAddress():"");
json.put("receiverName", commonDto.getEmpName());
json.put("receiverPhone", commonDto.getEmpTel());
json.put("parkInfo", dmVisitorSmsConfigPo!=null?dmVisitorSmsConfigPo.getParkPrompt():"");
//给访客发送短信
SmsReqEntity send = new SmsReqEntity();

send.setPhone(commonDto.getVisitorTel());
send.setTemplate(smsProperties.getVisitorTemplate());
send.setDataMap(json.toJSONString());
remoteSmsService.sendSms(send);
visitRecords.setVisitorId(v.getId());

}

} else {
System.err.println("emp not exist");
return output(ResponseCode.DATA_NOT_EXISTS, "员工").toJSON();
}
} catch (Exception ee) {
ee.printStackTrace();
Integer res = dmVisitRecordsMapper.insert(visitRecords);
DmVisitorOperateLogDto visitorOperateLogPo = visitorOperateLogService.initData(v.getId(), commonDto.getEmpId(), DmVisitorOperateLogDto.BUSINESS_TYPE_CREATE, "createVisitRecord", JSON.toJSONString(commonDto), JSON.toJSONString(res));
operateLogs.add(visitorOperateLogPo);
if (!operateLogs.isEmpty()) {
visitorOperateLogService.insertBatch(operateLogs);
}
redisTemplate.opsForValue().increment("dashboard:create_visitor_info", 1);
if (null != commonDto.getVisitorTel()){//有访客电话,发送短信
R<String> rStr = visitRecordsService.sendSms(visitRecords);
if (rStr.isFail()) {
return output(-1, rStr.getMsg()).toJSON();
}
}


return outputSuccess().toJSON();
}

@@ -304,11 +240,6 @@ public class DmVisitorInnerApiController extends MyBaseApiController {

JSONObject json = new JSONObject();

/*json.put("empId", empId);
DmStaffPo e = dmStaffMapper.selectById(v.getUserId());
json.put("phone", e.getPhone());
json.put("visitorName", visitorName);
json.put("visitorId", v.getVisitorId());*/
List<DmVisitRecordsDto> dtos = new ArrayList<>();

v.forEach(item->{
@@ -364,6 +295,15 @@ public class DmVisitorInnerApiController extends MyBaseApiController {
return outputSuccess(json).toJSON();
}

@InnerAuth
@GetMapping(value = "visitors")
public com.alibaba.fastjson2.JSONObject visitors(){
JSONObject json = new JSONObject();
List<DmVisitorsPo> v = dmVisitorsMapper.selectList(null);
json.put("data", v);
return outputSuccess(json).toJSON();
}


@Autowired
private SmsProperties smsProperties;
@@ -373,13 +313,13 @@ public class DmVisitorInnerApiController extends MyBaseApiController {
@PostMapping(value = "send-sms")
public com.alibaba.fastjson2.JSONObject sendSms(@RequestParam(value = "type") Integer type){
List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_allpeople_type");
List<String> vals = dictDataDtos.stream().map(SysDictDataPo::getValue).collect(Collectors.toList());
List<String> vals = dictDataDtos.stream().map(SysDictDataPo::getValue).toList();

if (!vals.contains(type.toString())) {
return AjaxResult.error("传入的参数可能有误").toJson();
}

List<Integer> ll = new ArrayList<Integer>();
List<Integer> ll = new ArrayList<>();
ll.add(type);
ll.add(DmTenantReceiverPo.ALL_TYPE);
List<DmTenantReceiverPo> list = receiverMapper.selectList(Wrappers.<DmTenantReceiverPo>query().lambda().in(DmTenantReceiverPo::getPersonType, ll.toArray())).stream().toList();


+ 25
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/dto/DmVisitorOperateLogDto.java 파일 보기

@@ -0,0 +1,25 @@
package com.xueyi.system.staff.domain.dto;

import com.xueyi.system.staff.domain.po.DmVisitorOperateLogPo;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serial;

/**
* 租户访客接待短信模板配置 数据传输对象
*
* @author xueyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DmVisitorOperateLogDto extends DmVisitorOperateLogPo {

@Serial
private static final long serialVersionUID = 1L;

public static final Integer BUSINESS_TYPE_CREATE = 1;
public static final Integer BUSINESS_TYPE_UPDATE = 2;
public static final Integer BUSINESS_TYPE_DELETE = 3;
public static final Integer BUSINESS_TYPE_OTHER = 0;
}

+ 17
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/model/DmVisitorOperateLogConverter.java 파일 보기

@@ -0,0 +1,17 @@
package com.xueyi.system.staff.domain.model;

import com.xueyi.common.core.web.entity.model.BaseConverter;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.po.DmVisitorOperateLogPo;
import com.xueyi.system.staff.domain.query.DmVisitorOperateLogQuery;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;

/**
* 访客 对象映射器
*
* @author xueyi
*/
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface DmVisitorOperateLogConverter extends BaseConverter<DmVisitorOperateLogQuery, DmVisitorOperateLogDto, DmVisitorOperateLogPo> {
}

+ 6
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/po/DmEmpAttendancePo.java 파일 보기

@@ -113,5 +113,11 @@ public class DmEmpAttendancePo extends TBaseEntity {
'}';
}

public DmEmpAttendancePo(){
super();
this.setWorkDuration(0);
this.setCreateTime(MyDateUtils.currentDateToLocalDateTime());
this.setUpdateTime(MyDateUtils.currentDateToLocalDateTime());
}

}

+ 61
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/po/DmVisitorOperateLogPo.java 파일 보기

@@ -0,0 +1,61 @@
package com.xueyi.system.staff.domain.po;

import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xueyi.common.core.annotation.Excel;
import com.xueyi.common.core.web.tenant.base.TBaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serial;
import java.time.LocalDateTime;

/**
* 操作日志 持久化对象
*
* @author xueyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "dm_visitor_operate_log",excludeProperty = {"name","sort","createBy","createTime","updateBy","updateTime","remark","status"})
public class DmVisitorOperateLogPo extends TBaseEntity {

@Serial
private static final long serialVersionUID = 1L;

/** 操作模块 */
protected String title;

/** 业务类型(0其它 1新增 2修改 3删除) */
protected Integer businessType;

/** 请求方法 */
protected String method;


protected Long visitorId;

/** 操作Id */
protected Long userId;

/** 操作人员账号 */
protected String userName;

/** 操作人员名称 */
protected String userNick;

/** 请求参数 */
protected String param;
/** 返回参数 */
protected String jsonResult;


/** 操作时间 */
@OrderBy(sort = 10)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
protected LocalDateTime operateTime;

}

+ 21
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/domain/query/DmVisitorOperateLogQuery.java 파일 보기

@@ -0,0 +1,21 @@
package com.xueyi.system.staff.domain.query;

import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.staff.domain.po.DmVisitorOperateLogPo;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serial;

/**
* 访客 数据查询对象
*
* @author xueyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DmVisitorOperateLogQuery extends DmVisitorOperateLogPo {

@Serial
private static final long serialVersionUID = 1L;
}

+ 0
- 59
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/PassRecordsGraphQLQueryResolver.java 파일 보기

@@ -1,59 +0,0 @@
package com.xueyi.system.staff.graphql;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.system.api.pass.domain.dto.DmRecognizedRecordsDto;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import com.xueyi.system.pass.domain.model.DmRecognizedRecordsConverter;
import com.xueyi.system.pass.mapper.DmRecognizedRecordsMapper;
import graphql.kickstart.tools.GraphQLQueryResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

/*
* @author yk
* @description
* @date 2023-12-25 19:55
*/

@Component
class PassRecordsGraphQLQueryResolver implements GraphQLQueryResolver {
@Autowired
private DmRecognizedRecordsMapper mapper;

@Autowired
private DmRecognizedRecordsConverter converter;


public DmRecognizedRecordsDto passRecord(Long id) {
return converter.mapperDto(mapper.selectById(id));
}

public List<DmRecognizedRecordsDto> passRecords(String userName, Long userId, Integer type, LocalDate startDate, LocalDate endDate){
QueryWrapper<DmRecognizedRecordsPo> query = new QueryWrapper<>();

if (StringUtils.isNotEmpty(userName)) {
query.like("user_name", userName);
}

if (null != userId) {
query.eq("user_id", userId);
}

if (null != type) {
query.eq("type", type);
}

if (null != startDate && null != endDate){
query.between("recognized_time", LocalDateTimeUtil.format(startDate, MyDateUtils.DEFAULT_DATE_PATTERN),LocalDateTimeUtil.format(endDate, MyDateUtils.DEFAULT_DATE_PATTERN));
}

return mapper.selectList(query).stream().map(t->converter.mapperDto(t)).collect(Collectors.toList());
}
}

+ 44
- 10
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitRecordGraphQLMutationResolver.java 파일 보기

@@ -1,22 +1,23 @@
package com.xueyi.system.staff.graphql;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
import com.alibaba.fastjson.JSON;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitRecordsDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitRecordsPo;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.api.staff.domain.dto.DmVisitCommonDto;
import com.xueyi.system.api.staff.domain.dto.GraphqlVisitRecordInput;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.model.DmVisitRecordsConverter;
import com.xueyi.system.staff.domain.model.DmVisitorsConverter;
import com.xueyi.system.staff.domain.query.DmVisitRecordsQuery;
import com.xueyi.system.staff.mapper.DmVisitRecordsMapper;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import com.xueyi.system.staff.service.impl.DmVisitorOperateLogServiceImpl;
import graphql.kickstart.tools.GraphQLMutationResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/*
* @author yk
@@ -35,12 +36,45 @@ class VisitRecordGraphQLMutationResolver implements GraphQLMutationResolver {
@Autowired
private DmVisitRecordsConverter converter;

@Autowired
private DmVisitorsConverter visitorsConverter;

@Autowired
private DmVisitorOperateLogServiceImpl visitorLogsService;

public DmVisitRecordsDto createVisitRecord(DmVisitRecordsDto input, Long staffId){
Map<String, Object> map = new HashMap<>();
map.put("input", input);
map.put("staffId", staffId);
input.setId(IdUtil.getSnowflakeNextId());
Boolean result = mapper.insert(input) > 0;
DmVisitorsDto visitorsPo = visitorsConverter.mapperDto(visitorsMapper.selectById(input.getVisitorId()));
input.setVisitor(visitorsPo);
DmVisitorOperateLogDto operateLogPo = visitorLogsService.initData(input.getVisitorId(), staffId, DmVisitorOperateLogDto.BUSINESS_TYPE_CREATE, "createVisitRecord", JSON.toJSONString(map),JSON.toJSONString(result));
visitorLogsService.insert(operateLogPo);
return result?input:null;
}

public boolean saveVisitRecord(DmVisitRecordsPo input){
return mapper.insert(input) > 0;
public DmVisitRecordsDto updateVisitRecord(DmVisitRecordsDto input, Long staffId){
Map<String, Object> map = new HashMap<>();
map.put("input", input);
map.put("staffId", staffId);
Boolean result = mapper.updateById(input) > 0;
DmVisitorsDto visitorsPo = visitorsConverter.mapperDto(visitorsMapper.selectById(input.getVisitorId()));
input.setVisitor(visitorsPo);
DmVisitorOperateLogDto operateLogPo = visitorLogsService.initData(input.getVisitorId(), staffId, DmVisitorOperateLogDto.BUSINESS_TYPE_UPDATE, "updateVisitRecord",JSON.toJSONString(map),JSON.toJSONString(result));
visitorLogsService.insert(operateLogPo);
return input;
}

public Boolean deleteVisitRecord(Long id){
return mapper.deleteById(id) > 0;
public Boolean deleteVisitRecord(Long id, Long staffId){
DmVisitRecordsPo recordsPo = mapper.selectById(id);
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("staffId", staffId);
Boolean result = mapper.deleteById(id) > 0;
DmVisitorOperateLogDto operateLogPo = visitorLogsService.initData(recordsPo.getVisitorId(), staffId, DmVisitorOperateLogDto.BUSINESS_TYPE_DELETE, "deleteVisitRecord", JSON.toJSONString(map), JSON.toJSONString(result));
visitorLogsService.insert(operateLogPo);
return result;
}
}

+ 10
- 3
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitRecordsGraphQLQueryResolver.java 파일 보기

@@ -38,10 +38,13 @@ class VisitRecordsGraphQLQueryResolver implements GraphQLQueryResolver {
private DmVisitorsConverter visitorsConverter;

public DmVisitRecordsDto visitRecord(Long id) {
return converter.mapperDto(mapper.selectById(id));
DmVisitRecordsDto dto = converter.mapperDto(mapper.selectById(id));
DmVisitorsPo po = visitorsMapper.selectOneById(dto.getVisitorId());
dto.setVisitor(visitorsConverter.mapperDto(po));
return dto;
}

public List<DmVisitRecordsDto> visitRecords(String receiverName, String receiverPhone, Long visitorId){
public List<DmVisitRecordsDto> visitRecords(String receiverName, String receiverPhone, Long visitorId, Integer limit){
QueryWrapper<DmVisitRecordsPo> query = new QueryWrapper<>();

if (StringUtils.isNotEmpty(receiverName)) {
@@ -55,10 +58,14 @@ class VisitRecordsGraphQLQueryResolver implements GraphQLQueryResolver {
if (null != visitorId) {
query.eq("visitor_id", visitorId);
}
query.orderByDesc("id");
if (null!= limit) {
query.last("limit " + limit);
}

return mapper.selectList(query).stream().map(
t -> {
DmVisitorsPo po = visitorsMapper.selectById(t.getVisitorId());
DmVisitorsPo po = visitorsMapper.selectOneById(t.getVisitorId());
DmVisitRecordsDto dto = converter.mapperDto(t);
dto.setVisitor(visitorsConverter.mapperDto(po));
return dto;


+ 47
- 21
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorGraphQLMutationResolver.java 파일 보기

@@ -1,15 +1,23 @@
package com.xueyi.system.staff.graphql;

import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.fastjson.JSON;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.api.resource.domain.po.DmResourcesPo;
import com.xueyi.system.resource.mapper.DmResourcesMapper;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.model.DmVisitorsConverter;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import com.xueyi.system.staff.service.impl.DmVisitorOperateLogServiceImpl;
import graphql.kickstart.tools.GraphQLMutationResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;


/*
* @author yk
@@ -22,37 +30,55 @@ class VisitorGraphQLMutationResolver implements GraphQLMutationResolver {
@Autowired
private DmVisitorsMapper mapper;

@Autowired
private DmVisitorsConverter converter;

@Autowired
private DmResourcesMapper resourcesMapper;

@Autowired
private DmVisitorOperateLogServiceImpl visitorLogsService;

public boolean saveVisitor(String name, String nickname, String phone, Boolean isVip, Boolean flexVisit, Boolean isBlock, Long resourceId){
DmVisitorsPo dto =new DmVisitorsPo();
dto.setPhone(phone);
dto.setNickname(nickname);
dto.setName(name);
dto.setIsVip(isVip);
if (BooleanUtils.isTrue(isVip)) {
dto.setType(9L);
private DmVisitorsDto initPo(DmVisitorsDto po){
if (BooleanUtils.isTrue(po.getIsVip())) {
po.setType(9L);
} else {
dto.setType(8L);
po.setType(8L);
}
dto.setFlexVisit(flexVisit);
dto.setIsBlock(isBlock);
dto.setResourceId(resourceId);
if (null != resourceId) {
DmResourcesPo resourcesPo = resourcesMapper.selectById(resourceId);
if (null != po.getResourceId() && null == po.getAvatar()) {
DmResourcesPo resourcesPo = resourcesMapper.selectById(po.getResourceId());
if (null != resourcesPo) {
dto.setAvatar(resourcesPo.getUrl());
po.setAvatar(resourcesPo.getUrl());
}
}
return mapper.updateById(dto) > 0;
return po;
}

public DmVisitorsDto updateVisitor(DmVisitorsDto po, Long staffId){
Map<String, Object> map = new HashMap<>();
map.put("input", po);
map.put("staffId", staffId);
Boolean result = mapper.updateOne(initPo(po)) > 0;
DmVisitorOperateLogDto operateLogPo = visitorLogsService.initData(po.getId(),staffId, DmVisitorOperateLogDto.BUSINESS_TYPE_UPDATE, "updateVisitor",JSON.toJSONString(map),JSON.toJSONString(result));
visitorLogsService.insert(operateLogPo);
return result ? po : null;
}

public DmVisitorsDto createVisitor(DmVisitorsDto po, Long staffId){
Map<String, Object> map = new HashMap<>();
map.put("input", po);
map.put("staffId", staffId);
po.setId(IdUtil.getSnowflakeNextId());
Boolean result = mapper.insert(initPo(po)) > 0;
DmVisitorOperateLogDto operateLogPo = visitorLogsService.initData(po.getId(),staffId, DmVisitorOperateLogDto.BUSINESS_TYPE_CREATE, "createVisitor",JSON.toJSONString(map),JSON.toJSONString(result));
visitorLogsService.insert(operateLogPo);
return result ? po : null;
}

public Boolean deleteVisitor(Long id){
return mapper.deleteById(id) > 0;
public Boolean deleteVisitor(Long id, Long staffId){
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("staffId", staffId);
Boolean result = mapper.deleteById(id) > 0;
DmVisitorOperateLogDto operateLogPo = visitorLogsService.initData(id,staffId, DmVisitorOperateLogDto.BUSINESS_TYPE_DELETE, "deleteVisitor",JSON.toJSONString(map),JSON.toJSONString(result));
visitorLogsService.insert(operateLogPo);
return result;
}
}

+ 1
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorGraphQLQuery.java 파일 보기

@@ -48,6 +48,7 @@ class VisitorGraphQLQueryResolver implements GraphQLQueryResolver {
if (StringUtils.isNotEmpty(phone)) {
query.eq("phone", phone);
}
query.orderByDesc("id");

return mapper.selectList(query).stream().map(t->converter.mapperDto(t)).toList();
}


+ 63
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorLogsGraphQLQueryResolver.java 파일 보기

@@ -0,0 +1,63 @@
package com.xueyi.system.staff.graphql;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.system.staff.domain.po.DmVisitorOperateLogPo;
import com.xueyi.system.staff.mapper.DmVisitorOperateLogMapper;
import graphql.kickstart.tools.GraphQLQueryResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.List;

/*
* @author yk
* @description
* @date 2023-12-25 19:55
*/

@Component
class VisitorLogsGraphQLQueryResolver implements GraphQLQueryResolver {
@Autowired
private DmVisitorOperateLogMapper mapper;



public DmVisitorOperateLogPo visitorLog(Long id) {
return mapper.selectById(id);
}

public List<DmVisitorOperateLogPo> visitorLogs(String userName, Long userId, Long visitorId, Integer businessType, LocalDate startDate, LocalDate endDate, Integer limit){
QueryWrapper<DmVisitorOperateLogPo> query = new QueryWrapper<>();

if (StringUtils.isNotEmpty(userName)) {
query.like("user_name", userName);
}

if (null != userId) {
query.eq("user_id", userId);
}

if (null != visitorId) {
query.eq("visitor_id", visitorId);
}

if (null != businessType) {
query.eq("business_type", businessType);
}
query.orderByDesc("id");

if (null!= limit) {
query.last("limit " + limit);
}

if (null != startDate && null != endDate){
query.between("operate_time", LocalDateTimeUtil.format(startDate, MyDateUtils.DEFAULT_DATE_PATTERN),LocalDateTimeUtil.format(endDate, MyDateUtils.DEFAULT_DATE_PATTERN));
}

return mapper.selectList(query);
}
}

+ 89
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/VisitorPassRecordsGraphQLQueryResolver.java 파일 보기

@@ -0,0 +1,89 @@
package com.xueyi.system.staff.graphql;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.api.pass.domain.dto.DmRecognizedRecordsDto;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import com.xueyi.system.pass.domain.model.DmRecognizedRecordsConverter;
import com.xueyi.system.pass.mapper.DmRecognizedRecordsMapper;
import com.xueyi.system.staff.domain.model.DmVisitorsConverter;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import graphql.kickstart.tools.GraphQLQueryResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

/*
* @author yk
* @description
* @date 2023-12-25 19:55
*/

@Component
class VisitorPassRecordsGraphQLQueryResolver implements GraphQLQueryResolver {
@Autowired
private DmRecognizedRecordsMapper mapper;

@Autowired
private DmRecognizedRecordsConverter converter;

@Autowired
private DmVisitorsMapper visitorsMapper;


@Autowired
private DmVisitorsConverter visitorsConverter;


public DmRecognizedRecordsDto visitorPassRecord(Long id) {
DmRecognizedRecordsDto recognizedRecordsDto = converter.mapperDto(mapper.selectById(id));
DmVisitorsPo po = visitorsMapper.selectOneById(recognizedRecordsDto.getUserId());
if (null != po) {
recognizedRecordsDto.setVisitor(visitorsConverter.mapperDto(po));
recognizedRecordsDto.setUserName(po.getName());
}
return recognizedRecordsDto;
}

public List<DmRecognizedRecordsDto> visitorPassRecords(String userName, Long userId, Integer type, LocalDate startDate, LocalDate endDate, Integer limit){
QueryWrapper<DmRecognizedRecordsPo> query = new QueryWrapper<>();

if (StringUtils.isNotEmpty(userName)) {
query.like("user_name", userName);
}

if (null != userId) {
query.eq("user_id", userId);
}

if (null != type) {
query.eq("type", type);
} else {
query.in("type", 8, 9, 10);
}

if (null != startDate && null != endDate){
query.between("recognized_time", LocalDateTimeUtil.format(startDate, MyDateUtils.DEFAULT_DATE_PATTERN),LocalDateTimeUtil.format(endDate, MyDateUtils.DEFAULT_DATE_PATTERN));
}
query.orderByDesc("id");
if (null!= limit) {
query.last("limit " + limit);
}
return mapper.selectList(query).stream().map(t->
{
DmRecognizedRecordsDto recognizedRecordsDto = converter.mapperDto(t);
DmVisitorsPo po = visitorsMapper.selectOneById(t.getUserId());
if (null != po) {
recognizedRecordsDto.setVisitor(visitorsConverter.mapperDto(po));
recognizedRecordsDto.setUserName(po.getName());
}
return recognizedRecordsDto;
}).collect(Collectors.toList());
}
}

+ 0
- 89
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/graphql/config/GraphQLConfig.java 파일 보기

@@ -1,89 +0,0 @@
package com.xueyi.system.staff.graphql.config;

import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.GraphQLContext;
import graphql.execution.instrumentation.ExecutionStrategyInstrumentationContext;
import graphql.execution.instrumentation.Instrumentation;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldParameters;
import graphql.execution.instrumentation.parameters.InstrumentationValidationParameters;
import graphql.kickstart.autoconfigure.tools.GraphQLJavaToolsAutoConfiguration;
import graphql.kickstart.tools.GraphQLResolver;
import graphql.kickstart.tools.SchemaParser;
import graphql.language.Document;
import graphql.schema.GraphQLSchema;
import graphql.validation.ValidationError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import java.util.List;

/**
* @author yk
* @description
* @date 2024-01-04 22:03
*/
@Configuration
@Import(GraphQLJavaToolsAutoConfiguration.class)
public class GraphQLConfig {

@Bean
public GraphQL graphQL(List<GraphQLResolver<?>> resolvers, List<SchemaParser> schemaParsers, GraphQLSchema graphQLSchema) {
return GraphQL.newGraphQL(graphQLSchema)
.instrumentation(new SimpleAuthInstrumentation())
.build();
}

private static class SimpleAuthInstrumentation implements Instrumentation {
Logger logger = LoggerFactory.getLogger(SimpleAuthInstrumentation.class);

@Override
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
return null;
}

@Override
public InstrumentationContext<Document> beginParse(InstrumentationExecutionParameters parameters) {
return null;
}

@Override
public InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters) {
return null;
}

@Override
public InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters parameters) {
GraphQLContext context = parameters.getExecutionContext().getGraphQLContext();

// 从上下文中获取请求头中的token
String token = context.get("Authorization");
logger.error("token: {}", token);
return null;
}


@Override
public ExecutionStrategyInstrumentationContext beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters) {
return null;
}

@Override
public InstrumentationContext<ExecutionResult> beginField(InstrumentationFieldParameters parameters) {
return null;
}

@Override
public InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters) {
return null;
}
}
}

+ 13
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/manager/IDmVisitorOperateLogManager.java 파일 보기

@@ -0,0 +1,13 @@
package com.xueyi.system.staff.manager;

import com.xueyi.common.web.entity.manager.IBaseManager;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.query.DmVisitorOperateLogQuery;

/**
* 访客管理 数据封装层
*
* @author xueyi
*/
public interface IDmVisitorOperateLogManager extends IBaseManager<DmVisitorOperateLogQuery, DmVisitorOperateLogDto> {
}

+ 35
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/manager/impl/DmVisitorOperateLogManager.java 파일 보기

@@ -0,0 +1,35 @@
package com.xueyi.system.staff.manager.impl;

import com.xueyi.common.core.constant.basic.OperateConstants;
import com.xueyi.common.web.entity.domain.SlaveRelation;
import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.digitalmans.domain.merge.DmReceptionVisitorMerge;
import com.xueyi.system.digitalmans.mapper.merge.DmReceptionVisitorMergeMapper;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.model.DmVisitorOperateLogConverter;
import com.xueyi.system.staff.domain.model.DmVisitorsConverter;
import com.xueyi.system.staff.domain.po.DmVisitorOperateLogPo;
import com.xueyi.system.staff.domain.query.DmVisitorOperateLogQuery;
import com.xueyi.system.staff.domain.query.DmVisitorsQuery;
import com.xueyi.system.staff.manager.IDmVisitorOperateLogManager;
import com.xueyi.system.staff.manager.IDmVisitorsManager;
import com.xueyi.system.staff.mapper.DmVisitorOperateLogMapper;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static com.xueyi.system.api.digitalmans.domain.merge.MergeGroup.Visitor_DmReceptionVisitorMerge_GROUP;

/**
* 访客管理 数据封装层处理
*
* @author xueyi
*/
@Component
public class DmVisitorOperateLogManager extends BaseManagerImpl<DmVisitorOperateLogQuery, DmVisitorOperateLogDto, DmVisitorOperateLogPo, DmVisitorOperateLogMapper, DmVisitorOperateLogConverter> implements IDmVisitorOperateLogManager {

}

+ 12
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/mapper/DmVisitorOperateLogMapper.java 파일 보기

@@ -0,0 +1,12 @@
package com.xueyi.system.staff.mapper;

import com.xueyi.common.datasource.annotation.Isolate;
import com.xueyi.common.web.entity.mapper.BaseMapper;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.po.DmVisitorOperateLogPo;
import com.xueyi.system.staff.domain.query.DmVisitorOperateLogQuery;


@Isolate
public interface DmVisitorOperateLogMapper extends BaseMapper<DmVisitorOperateLogQuery, DmVisitorOperateLogDto, DmVisitorOperateLogPo> {
}

+ 5
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/mapper/DmVisitorsMapper.java 파일 보기

@@ -14,4 +14,9 @@ import com.xueyi.system.staff.domain.query.DmVisitorsQuery;
@Isolate
public interface DmVisitorsMapper extends BaseMapper<DmVisitorsQuery, DmVisitorsDto, DmVisitorsPo> {
Long addOne (DmVisitorsPo visitorsPo);

Long updateOne (DmVisitorsPo visitorsPo);

//软删除也会查询出来
DmVisitorsPo selectOneById (Long id);
}

+ 13
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/IDmVisitorOperateLogService.java 파일 보기

@@ -0,0 +1,13 @@
package com.xueyi.system.staff.service;

import com.xueyi.common.web.entity.service.IBaseService;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.query.DmVisitorOperateLogQuery;

/**
* 访客日志管理 服务层
*
* @author xueyi
*/
public interface IDmVisitorOperateLogService extends IBaseService<DmVisitorOperateLogQuery, DmVisitorOperateLogDto> {
}

+ 3
- 5
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmEmpAttendanceServiceImpl.java 파일 보기

@@ -57,8 +57,7 @@ public class DmEmpAttendanceServiceImpl extends BaseServiceImpl<DmEmpAttendanceQ
@TenantIgnore(tenantLine = true)
public Integer selectCountIgnoreTenant() {
if (redisTemplate.hasKey("broadcast:attendance")) {
Integer attendance = (Integer) redisTemplate.opsForValue().get("broadcast:attendance");
return attendance;
return (Integer) redisTemplate.opsForValue().get("broadcast:attendance");
} else {
Long attendance = attendanceMapper.selectCount(new QueryWrapper<>());
redisTemplate.opsForValue().set("dashboard:attendance", attendance);
@@ -81,7 +80,7 @@ public class DmEmpAttendanceServiceImpl extends BaseServiceImpl<DmEmpAttendanceQ
List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_attendance_desc");
Map<String, String> dictMap = dictDataDtos.stream().collect(Collectors.toMap(SysDictDataDto::getValue, SysDictDataDto::getLabel));

List<LocalDate> dateRange = startDate.datesUntil(endDate.plusDays(1)).collect(Collectors.toList());
List<LocalDate> dateRange = startDate.datesUntil(endDate.plusDays(1)).toList();

return grouped.entrySet().stream()
.map(entry -> {
@@ -94,8 +93,7 @@ public class DmEmpAttendanceServiceImpl extends BaseServiceImpl<DmEmpAttendanceQ
row.add(status);
}
return row;
})
.collect(Collectors.toList());
}).toList();
}

public void updRedisCount(){


+ 94
- 85
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmStaffServiceImpl.java 파일 보기

@@ -1,16 +1,19 @@
package com.xueyi.system.staff.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.web.annotation.TenantIgnore;
import com.xueyi.common.web.entity.service.impl.BaseServiceImpl;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.system.api.holiday.domain.po.DmHolidayPo;
import com.xueyi.system.api.organize.domain.vo.SysDeptExt;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import com.xueyi.system.api.staff.domain.dto.DmStaffDto;
import com.xueyi.system.api.staff.domain.po.DmStaffPo;
import com.xueyi.system.api.staff.domain.vo.DmStaffFeature;
import com.xueyi.system.common.domain.po.DmHolidayPo;
import com.xueyi.system.common.service.IDmHolidayService;
import com.xueyi.system.organize.mapper.SysDeptExtMapper;
import com.xueyi.system.staff.domain.po.DmEmpAttendancePo;
@@ -24,12 +27,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 人员管理 服务层处理
@@ -39,26 +40,19 @@ import java.util.Map;
@Service
public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto, IDmStaffManager> implements IDmStaffService {

// Map<String, Integer> STATUS_TYPE = MapUtil.;

private Logger logger = LoggerFactory.getLogger(DmStaffServiceImpl.class);
private Map<String, Integer> statusMap;

public static final Integer ATTENDANCE_STATUS_NORMAL = 0;
public static final Integer ATTENDANCE_STATUS_BE_LATER = 1;
public static final Integer ATTENDANCE_STATUS_LEAVE_EARLY = 2;
public static final Integer ATTENDANCE_STATUS_ABSENCE = 3;
public static final Integer ATTENDANCE_STATUS_OVERTIME = 4;
public static final Integer ATTENDANCE_STATUS_LATER_AND_EARLY = 6;


@Autowired
private IDmHolidayService holidayService;

@PostConstruct
public void initializeMap() {
// 初始化Map
statusMap = new HashMap<>();
statusMap.put("NORMAL", 0);
statusMap.put("BE_LATER", 1);
statusMap.put("LEAVE_EARLY", 2);
statusMap.put("ABSENCE", 3);
statusMap.put("OVERTIME", 4);
statusMap.put("LATER_AND_EARLY", 6);
// 继续初始化其他常量...
}
@Autowired
DmStaffMapper staffMapper;

@@ -88,7 +82,6 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto
@TenantIgnore(tenantLine = true)
public List<DmStaffPo> selectStaffList(DmStaffPo staff) {
List<DmStaffPo> result = staffMapper.selectStaffList(staff);
List<DmStaffPo> po = staffMapper.selectList(null);
return result;
}

@@ -140,99 +133,115 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto
attendancePo.setUserId(po.getId());
attendancePo.setUserName(po.getUserName());
attendancePo.setTenantId(po.getTenantId());
attendancePo.setDescStatus(3);
attendancePo.setDescStatus(ATTENDANCE_STATUS_ABSENCE);
attendancePo.setUserType(Long.parseLong(po.getUserType()));
attendancePo.setDeptId(po.getDeptId());
attendancePo.setDateStr(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN));
attendancePos.add(attendancePo);
}
}
if (attendancePos.size() > 0) {
if (!attendancePos.isEmpty()) {
dmEmpAttendanceMapper.insertBatch(attendancePos);
}
}

public DmEmpAttendancePo newInit(LocalDateTime checkDateTime, String onDutyHourEnd) {
DmEmpAttendancePo ea = new DmEmpAttendancePo();
Date checkDate = MyDateUtils.localDateTimeToDate(checkDateTime);
ea.setCheckInTime(checkDate);
logger.info("考勤打卡时间1:{}", JSON.toJSONString(checkDateTime));
DmHolidayPo holidayPo = holidayService.isHoliday(checkDateTime.toLocalDate());
if (MyDateUtils.formatDate(checkDate, MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(onDutyHourEnd) > 0) {//识别时间比考勤上班打卡最晚时间更晚
ea.setDescStatus(ATTENDANCE_STATUS_BE_LATER); // 迟到
if (holidayPo.getHoliday() == 1) {
ea.setDescStatus(ATTENDANCE_STATUS_OVERTIME);
}
} else {//识别时间比考勤上班打卡最晚时间早
if (holidayPo.getHoliday() == 1) {
ea.setDescStatus(ATTENDANCE_STATUS_OVERTIME);
}
}
return ea;
}


public void updateOrInsertAttendance(DmRecognizedRecordsPo checkRecords) {
if (null == checkRecords.getUserId()) {
return ;
public DmEmpAttendancePo judgeAttendanceDescStatus(DmEmpAttendancePo po, LocalDateTime checkDateTime, Long deptId){
SysDeptExt ext = sysDeptExtMapper.selectWorkTimeByDeptId(deptId);
Date checkDate = MyDateUtils.localDateTimeToDate(checkDateTime);
if (null == po) {
return newInit(checkDateTime, ext.getOnDutyHourEnd());
}
Long userId = checkRecords.getUserId();
DmStaffPo emp = this.selectById(userId);
if (null == emp) {
return ;
logger.info("考勤打卡时间2:{}", JSON.toJSONString(checkDateTime));
if (po.getCheckInTime() == null){
po.setCheckInTime(checkDate);
} else {
po.setCheckOutTime(checkDate);
}

Date checkTime = MyDateUtils.localDateTimeToDate(checkRecords.getRecognizedTime());
String checkTimeDateStr = MyDateUtils.formatDate(checkTime, MyDateUtils.DEFAULT_DATE_PATTERN);
if (StringUtils.isEmpty(checkTimeDateStr)) {
return ;
DmHolidayPo holidayPo = holidayService.isHoliday(checkDateTime.toLocalDate());
if (holidayPo.getHoliday() == 1) {//如果是节假日
po.setDescStatus(ATTENDANCE_STATUS_OVERTIME);//加班
return po;
}

DmEmpAttendancePo empAttendance = dmEmpAttendanceMapper.findByEmpAndDate(checkTimeDateStr, userId);
SysDeptExt ext = sysDeptExtMapper.selectWorkTimeByDeptId(emp.getDeptId());
logger.info("deptId:{}", emp.getDeptId());
logger.info("deptId:{}", po.getDeptId());
logger.info("ext:start-end:{} end-start:{}" ,ext.getOnDutyHourEnd(), ext.getOffDutyHourStart());

if (null != empAttendance) {

if (null == empAttendance.getCheckInTime()) {
empAttendance.setCheckInTime(checkTime);
if (po.getCheckInTime() != null && po.getCheckOutTime()== null) {//第一次打卡
if (MyDateUtils.formatDate(po.getCheckInTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(ext.getOnDutyHourEnd()) > 0) {//识别时间比考勤上班打卡最晚时间更晚
po.setDescStatus(ATTENDANCE_STATUS_LATER_AND_EARLY);
} else {
empAttendance.setCheckOutTime(checkTime);
}


if (null!=empAttendance.getCheckInTime() && null != empAttendance.getCheckOutTime()) {
Date cin = empAttendance.getCheckInTime();
Date cout = empAttendance.getCheckOutTime();
Integer diffMin = MyDateUtils.dateDiffMin(cin, cout);
empAttendance.setWorkDuration(diffMin);
po.setDescStatus(ATTENDANCE_STATUS_LEAVE_EARLY);
}

if (MyDateUtils.formatDate(checkTime, MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(ext.getOffDutyHourStart()) < 0) {
if (statusMap.get("NORMAL") == empAttendance.getDescStatus()) {
empAttendance.setDescStatus(statusMap.get("LEAVE_EARLY"));
} else if (statusMap.get("BE_LATER") == empAttendance.getDescStatus()){
empAttendance.setDescStatus(statusMap.get("LATER_AND_EARLY"));
return po;
} else if (po.getCheckInTime() != null && po.getCheckOutTime() != null) {//之后的打卡
if (MyDateUtils.formatDate(po.getCheckInTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(ext.getOffDutyHourStart()) < 0) {//识别时间比考勤下班打卡最早时间更早
if (MyDateUtils.formatDate(po.getCheckInTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(ext.getOnDutyHourEnd()) > 0) {//识别时间比考勤上班打卡最晚时间更晚
po.setDescStatus(ATTENDANCE_STATUS_LATER_AND_EARLY);
} else {//正常上班打卡
po.setDescStatus(ATTENDANCE_STATUS_LEAVE_EARLY);
}
} else { //如果修改考勤时间,则对应修改考勤状态
if (statusMap.get("LATER_AND_EARLY") == empAttendance.getDescStatus()) {
empAttendance.setDescStatus(statusMap.get("BE_LATER"));
} else if (statusMap.get("LEAVE_EARLY") == empAttendance.getDescStatus()){
empAttendance.setDescStatus(statusMap.get("NORMAL"));
} else {//正常下班打卡
if (MyDateUtils.formatDate(po.getCheckInTime(), MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(ext.getOnDutyHourEnd()) > 0) {//识别时间比考勤上班打卡最晚时间更晚
po.setDescStatus(ATTENDANCE_STATUS_BE_LATER);
} else {//正常上班打卡
po.setDescStatus(ATTENDANCE_STATUS_NORMAL);
}
}
QueryWrapper<DmEmpAttendancePo> wrapper = new QueryWrapper<>();
wrapper.eq("id",empAttendance.getId());
dmEmpAttendanceMapper.update(empAttendance, wrapper);
Date cin = po.getCheckInTime();
Date cout = po.getCheckOutTime();
Integer diffMin = MyDateUtils.dateDiffMin(cin, cout);
po.setWorkDuration(diffMin);
}
return po;
}

} else {
DmEmpAttendancePo ea = new DmEmpAttendancePo();
Date checkDate = checkTime;
ea.setCheckInTime(checkDate);
DmHolidayPo holidayPo = holidayService.isHoliday(checkDate);
if (MyDateUtils.formatDate(checkDate, MyDateUtils.DEFAULT_TIME_PATTERN).compareTo(ext.getOnDutyHourEnd()) > 0) {
ea.setDescStatus(statusMap.get("BE_LATER")); // 迟到
if (holidayPo.getHoliday() == 1) {
ea.setDescStatus(statusMap.get("OVERTIME"));
}
} else {
if (holidayPo.getHoliday() == 1) {
ea.setDescStatus(statusMap.get("OVERTIME"));
}
}

public void updateOrInsertAttendance(DmRecognizedRecordsPo checkRecords) {
if (ObjectUtil.isNull(checkRecords.getUserId())) {
return ;
}
LocalDateTime checkTime = checkRecords.getRecognizedTime();
String checkTimeDateStr = LocalDateTimeUtil.format(checkTime, MyDateUtils.DEFAULT_DATE_PATTERN);
if (StringUtils.isEmpty(checkTimeDateStr)) {//无打卡时间
return ;
}
Long userId = checkRecords.getUserId();
DmStaffPo emp = this.selectById(userId);
if (null == emp) {//无对应员工
return ;
}

DmEmpAttendancePo empAttendance = dmEmpAttendanceMapper.findByEmpAndDate(checkTimeDateStr, userId);
if (null != empAttendance) {//基本都会走这个控制段
empAttendance = judgeAttendanceDescStatus(empAttendance, checkTime, emp.getDeptId());
dmEmpAttendanceMapper.updateById(empAttendance);
} else {
DmEmpAttendancePo ea = judgeAttendanceDescStatus(empAttendance, checkTime, emp.getDeptId());
ea.setDateStr(MyDateUtils.formatDate(new Date(), MyDateUtils.DEFAULT_DATE_PATTERN));
ea.setUserId(userId);
ea.setUserName(emp.getUserName());
ea.setUserType(Long.parseLong(emp.getUserType()));
ea.setDeptId(emp.getDeptId());
ea.setWorkDuration(0);
ea.setCreateTime(MyDateUtils.currentDateToLocalDateTime());
ea.setUpdateTime(MyDateUtils.currentDateToLocalDateTime());
dmEmpAttendanceService.updRedisCount();

dmEmpAttendanceService.updRedisCount();
dmEmpAttendanceMapper.insert(ea);
}
}

+ 142
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmVisitRecordsServiceImpl.java 파일 보기

@@ -1,11 +1,41 @@
package com.xueyi.system.staff.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xueyi.common.core.constant.basic.SqlConstants;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.sms.configure.SmsProperties;
import com.xueyi.common.web.entity.service.impl.BaseServiceImpl;
import com.xueyi.common.web.utils.MyDateUtils;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitRecordsDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitRecordsPo;
import com.xueyi.system.api.digitalmans.domain.po.DmVisitorsPo;
import com.xueyi.system.api.sms.domain.vo.SmsReqEntity;
import com.xueyi.system.api.sms.feign.RemoteSmsService;
import com.xueyi.system.api.staff.domain.dto.DmVisitCommonDto;
import com.xueyi.system.api.staff.domain.po.DmStaffPo;
import com.xueyi.system.digitalmans.mapper.DmDigitalmanExtMapper;
import com.xueyi.system.digitalmans.mapper.DmDigitalmanMapper;
import com.xueyi.system.meeting.constant.VisitRecordStatus;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.po.DmVisitorSmsConfigPo;
import com.xueyi.system.staff.domain.query.DmVisitRecordsQuery;
import com.xueyi.system.staff.manager.IDmVisitRecordsManager;
import com.xueyi.system.staff.mapper.DmStaffMapper;
import com.xueyi.system.staff.mapper.DmVisitRecordsMapper;
import com.xueyi.system.staff.mapper.DmVisitorSmsConfigMapper;
import com.xueyi.system.staff.mapper.DmVisitorsMapper;
import com.xueyi.system.staff.service.IDmVisitRecordsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -21,10 +51,37 @@ import java.util.concurrent.TimeUnit;
@Service
public class DmVisitRecordsServiceImpl extends BaseServiceImpl<DmVisitRecordsQuery, DmVisitRecordsDto, IDmVisitRecordsManager> implements IDmVisitRecordsService {

private Logger log = LoggerFactory.getLogger(DmVisitRecordsServiceImpl.class);

private static final int CODE_LENGTH = 4;
private static final String REDIS_KEY_PREFIX = "visitor:verification_code:";

@Autowired
private RemoteSmsService smsService;

@Autowired
private DmVisitRecordsMapper visitRecordsMapper;

@Autowired
private DmVisitorsMapper visitorsMapper;

@Autowired
private SmsProperties smsProperties;

@Autowired
private DmVisitorSmsConfigMapper visitorSmsConfigMapper;

@Autowired
private DmDigitalmanExtMapper digitalmanExtMapper;
@Autowired
private DmDigitalmanMapper digitalmanMapper;

@Autowired
private DmStaffMapper staffMapper;

@Autowired
private DmVisitorOperateLogServiceImpl visitorOperateLogService;

@Autowired
private RedisTemplate<String, String> redisTemplate;

@@ -75,5 +132,90 @@ public class DmVisitRecordsServiceImpl extends BaseServiceImpl<DmVisitRecordsQue
}
}

public DmVisitRecordsPo initVisitRecord(DmVisitCommonDto commonDto){
DmVisitRecordsPo visitRecords = null;
DmStaffPo emp = staffMapper.selectOne(
Wrappers.<DmStaffPo>query().lambda()
.eq(DmStaffPo::getId, commonDto.getEmpId()).last(SqlConstants.LIMIT_ONE));
if (ObjectUtils.isNotEmpty(emp)) {
visitRecords = new DmVisitRecordsPo();
visitRecords.setDeptId(emp.getDeptId());
// visitRecords.setVisitorId(v.getId());
if (StringUtils.isNotEmpty(commonDto.getVisitDate())) {
visitRecords.setVisitDate(LocalDateTimeUtil.of(MyDateUtils.parseStrToDate(commonDto.getVisitDate(), MyDateUtils.DEFAULT_DATE_PATTERN)).toLocalDate());
}
visitRecords.setUserId(commonDto.getEmpId());
visitRecords.setRecordStatus(VisitRecordStatus.getRecordStatusStart());
String code = genVisitorCode();
visitRecords.setVisitorCode(code);
visitRecords.setReceiverName(commonDto.getEmpName());
visitRecords.setReceiverPhone(commonDto.getEmpTel());
}
return visitRecords;
}

public DmVisitorsPo initVisitor(DmVisitCommonDto commonDto){
DmVisitorsPo v = new DmVisitorsPo();
v.setId(IdUtil.getSnowflakeNextId());
v.setName(commonDto.getVisitorName());
v.setNickname(commonDto.getVisitorNickName());
v.setVisitorCompany(commonDto.getVisitCompany());
v.setPhone(commonDto.getVisitorTel());
v.setType(DmVisitorsDto.TYPE_NORMAL_VISITOR);
return v;
}


public R<String> sendSms(DmVisitRecordsPo po) {
log.info("sendSms po:{}", JSON.toJSONString(po));
if (null != po && null != po.getVisitorId()) {
DmVisitorsPo visitorsPo = visitorsMapper.selectById(po.getVisitorId());
SmsReqEntity send = new SmsReqEntity();
try {
if (null != visitorsPo && StringUtils.isNotEmpty(visitorsPo.getPhone())) {
DmVisitorSmsConfigPo dmVisitorSmsConfigPo = visitorSmsConfigMapper.selectOne(Wrappers.<DmVisitorSmsConfigPo>query().lambda().last(SqlConstants.LIMIT_ONE));

DmDigitalmanPo dmDigitalmanPo = digitalmanMapper.selectByCode(digitalmanExtMapper.selectOne(Wrappers.<DmDigitalmanExtPo>query().lambda().last(SqlConstants.LIMIT_ONE)).getManCode());

DmStaffPo staffPo = staffMapper.selectById(po.getUserId());

JSONObject json = new JSONObject();
String code = po.getVisitorCode();
if (code == null && po.getId() != null) {
code = genVisitorCode();
po.setVisitorCode(code);
visitRecordsMapper.updateById(po);
}

json.put("code", code);
json.put("nickName", visitorsPo.getName());
json.put("robotName", dmDigitalmanPo.getName());
json.put("dateTime", LocalDateTimeUtil.format(po.getVisitDate(), MyDateUtils.DEFAULT_DATE_PATTERN));
json.put("companyName", dmVisitorSmsConfigPo!=null?dmVisitorSmsConfigPo.getCompanyName():"");
json.put("companyAddr", dmVisitorSmsConfigPo!=null?dmVisitorSmsConfigPo.getCompanyAddress():"");
json.put("receiverName", staffPo!=null?staffPo.getUserName():"");
json.put("receiverPhone", staffPo!=null?staffPo.getPhone():"");
json.put("parkInfo", dmVisitorSmsConfigPo!=null?dmVisitorSmsConfigPo.getParkPrompt():"");
//给访客发送短信

send.setPhone(visitorsPo.getPhone());
send.setTemplate(smsProperties.getVisitorTemplate());
send.setDataMap(json.toJSONString());
JSONObject result = smsService.sendSms(send);

DmVisitorOperateLogDto visitorOperateLogPo = visitorOperateLogService.initData(po.getVisitorId(), po.getUserId(), DmVisitorOperateLogDto.BUSINESS_TYPE_OTHER, "sendSms", JSON.toJSONString(send), result.toJSONString());
visitorOperateLogService.insert(visitorOperateLogPo);
} else {
return R.fail("数据存在问题");
}

} catch (Exception e) {
log.error("发送短信异常", e.getMessage());
return R.fail("服务器错误,无法发送短信");
}
}
return R.ok("发送成功");
}


}

+ 41
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmVisitorOperateLogServiceImpl.java 파일 보기

@@ -0,0 +1,41 @@
package com.xueyi.system.staff.service.impl;

import com.xueyi.common.web.entity.service.impl.BaseServiceImpl;
import com.xueyi.system.api.staff.domain.po.DmStaffPo;
import com.xueyi.system.staff.domain.dto.DmVisitorOperateLogDto;
import com.xueyi.system.staff.domain.query.DmVisitorOperateLogQuery;
import com.xueyi.system.staff.manager.IDmVisitorOperateLogManager;
import com.xueyi.system.staff.mapper.DmStaffMapper;
import com.xueyi.system.staff.service.IDmVisitorOperateLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
* 访客管理 服务层处理
*
* @author xueyi
*/
@Service
public class DmVisitorOperateLogServiceImpl extends BaseServiceImpl<DmVisitorOperateLogQuery, DmVisitorOperateLogDto, IDmVisitorOperateLogManager> implements IDmVisitorOperateLogService {

@Autowired
private DmStaffMapper staffMapper;

public DmVisitorOperateLogDto initData(Long visitorId, Long staffId, Integer businessType, String funName, String parms, String result){
DmVisitorOperateLogDto operateLogPo = new DmVisitorOperateLogDto();
operateLogPo.setVisitorId(visitorId);
operateLogPo.setUserId(staffId);
DmStaffPo staffPo = staffMapper.selectById(staffId);
operateLogPo.setBusinessType(businessType);
operateLogPo.setMethod(funName);
operateLogPo.setUserName(staffPo.getUserName());
operateLogPo.setTitle("访客方面操作日志");
operateLogPo.setOperateTime(LocalDateTime.now());
operateLogPo.setParam(parms);
operateLogPo.setJsonResult(result);
return operateLogPo;
}

}

+ 2
- 2
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/utils/common/ImageUtil.java 파일 보기

@@ -118,7 +118,7 @@ public class ImageUtil {
}
}

protected String getNewFileName(String ext){
protected static String getNewFileName(String ext){
String random1 = String.valueOf(System.currentTimeMillis());
String random2 = UUID.randomUUID().toString().replaceAll("-", "");
return random1 + "_" + random2.substring(0, 8) + "."+ext;
@@ -248,7 +248,7 @@ public class ImageUtil {
}


public MultipartFile convertToMultipartFile(String base64String) {
public static MultipartFile convertToMultipartFile(String base64String) {
java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
try {
//Base64解码


+ 0
- 21
xueyi-modules/xueyi-system/src/main/resources/graphql/passRecords.graphqls 파일 보기

@@ -1,21 +0,0 @@
extend type Query {
passRecords(
userName:String
userId:Long
type:Int
startDate:Date
endDate:Date
): [PassRecord!]

passRecord(id:Long!): PassRecord
}


type PassRecord {
id: Long
userName: String
userId: Long
faceUrl: String
recognizedTime: Date
type: Int
}

+ 1
- 0
xueyi-modules/xueyi-system/src/main/resources/graphql/root.graphqls 파일 보기

@@ -1,6 +1,7 @@
scalar Long
scalar DateTime
scalar Date
scalar Time

type Query {



+ 24
- 10
xueyi-modules/xueyi-system/src/main/resources/graphql/visitRecords.graphqls 파일 보기

@@ -2,34 +2,48 @@ extend type Query {
visitRecords(
receiverName:String
receiverPhone:String
visitorId:Long
visitorId:ID
limit:Int
): [VisitRecord!]

visitRecord(id:Long!): VisitRecord
visitRecord(id:ID!): VisitRecord
}


input VisitRecordInput {
visitorId: Long!
id: ID
visitorId: ID!
visitDate: Date!
userId: Long
userId: ID
receiverName: String
receiverPhone: String
}

extend type Mutation {
saveVisitRecord(
createVisitRecord(
input:VisitRecordInput!
): Boolean
deleteVisitRecord(id:Long): Boolean
staffId: ID!
): VisitRecord

updateVisitRecord(
input:VisitRecordInput!
staffId: ID!
): VisitRecord
deleteVisitRecord(
id:ID!
staffId: ID!
): Boolean
}

type VisitRecord {
id: Long
visitorId: Long
userId: Long
id: ID
visitorId: ID
userId: ID
# 接待人姓名
receiverName: String
#接待人电话
receiverPhone: String
# 记录状态
recordStatus: Int
visitDate: Date
visitorCode: String


+ 36
- 13
xueyi-modules/xueyi-system/src/main/resources/graphql/visitor.graphqls 파일 보기

@@ -1,26 +1,44 @@
extend type Query {
visitors(
id: Long
id: ID
name: String
type: Int
phone: String
): [Visitor!]

visitor(id: Long): Visitor
visitor(id: ID): Visitor
}

input VisitorInput {
id: ID
name: String
nickname: String
phone: String
visitorCompany: String
# 是否是VIP
isVip:Boolean
# 是否可随时拜访
flexVisit:Boolean
# 是否可拜访
isBlock:Boolean
resourceId: ID
}

extend type Mutation {
saveVisitor(
name: String!
nickname: String
phone: String
isVip:Boolean
flexVisit:Boolean
isBlock:Boolean
resourceId: Long
): Boolean
createVisitor(
input: VisitorInput!
staffId: ID!
): Visitor
updateVisitor(
input: VisitorInput!
staffId: ID!
): Visitor

deleteVisitor(id: Long!): Boolean
deleteVisitor(
id: ID!,
staffId: ID!
): Boolean
}

type Visitor {
@@ -32,8 +50,13 @@ type Visitor {
type: Int
visitorCompany: String
avatar: String
# 是否是VIP
isVip:Boolean
# 是否可随时拜访
flexVisit:Boolean
# 是否可拜访
isBlock:Boolean
resourceId: Long
resourceId: ID
# 删除标识,1:已删除;0:未删除
delFlag: Int
}

+ 29
- 0
xueyi-modules/xueyi-system/src/main/resources/graphql/visitorLog.graphqls 파일 보기

@@ -0,0 +1,29 @@
extend type Query {
visitorLogs(
userName:String
userId:ID
visitorId:ID
businessType:Int
startDate:Date
endDate:Date
limit:Int
): [VisitorLog!]

visitorLog(id:ID!): VisitorLog
}


type VisitorLog {
id: ID
businessType: Int
method: String
visitorId: ID
userId: ID
userName: String
# 接口请求参数
param: String
# 接口返回消息
jsonResult: String
# 操作时间
operateTime: String
}

+ 26
- 0
xueyi-modules/xueyi-system/src/main/resources/graphql/visitorPassRecords.graphqls 파일 보기

@@ -0,0 +1,26 @@
extend type Query {
visitorPassRecords(
userName:String
userId:ID
type:Int
startDate:Date
endDate:Date
limit:Int
): [VisitorPassRecord!]

visitorPassRecord(id:ID!): VisitorPassRecord
}


type VisitorPassRecord {
id: ID
userName: String
userId: ID
faceUrl: String
# 通行时间
recognizedTime: String
createTime: Date
# 通行人员类型,10:外部特殊人员; 9:重要访客; 8:预约访客;
type: Int
visitor: Visitor
}

+ 20
- 0
xueyi-modules/xueyi-system/src/main/resources/mapper/staff/DmVisitorsMapper.xml 파일 보기

@@ -20,4 +20,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{avatar}
)
</insert >

<update id="updateOne" parameterType="DmVisitorsPo">
update dm_visitors
<set>
<if test="name != null ">name = #{name},</if>
<if test="nickname != null ">nickname = #{nickname},</if>
<if test="phone != null ">phone = #{phone},</if>
<if test="visitorCompany != null ">visitor_company = #{visitorCompany},</if>
<if test="flexVisit != null ">flex_visit = #{flexVisit},</if>
<if test="isBlock != null ">is_block = #{isBlock},</if>
<if test="isVip != null ">is_vip = #{isVip},</if>
<if test="avatar != null ">avatar = #{avatar},</if>
<if test="resourceId != null ">resource_id = #{resourceId},</if>
</set>
where id = #{id}
</update >

<select id="selectOneById" parameterType="Long" resultType="com.xueyi.system.api.digitalmans.domain.dto.DmVisitorsDto">
select * from dm_visitors where id = #{id}
</select>
</mapper>

+ 5
- 6
xueyi-modules/xueyi-tenant/src/main/java/com/xueyi/tenant/tenant/controller/TeTenantController.java 파일 보기

@@ -17,15 +17,12 @@ import com.xueyi.common.security.annotation.RequiresPermissions;
import com.xueyi.common.security.auth.Auth;
import com.xueyi.common.web.annotation.TenantIgnore;
import com.xueyi.common.web.entity.controller.BaseController;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.domain.po.SysEnterprisePo;
import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto;
import com.xueyi.tenant.api.tenant.domain.po.SysEnterpriseStaff;
import com.xueyi.tenant.api.tenant.domain.po.TeTenantPo;
import com.xueyi.tenant.api.tenant.domain.query.TeTenantQuery;
import com.xueyi.tenant.tenant.domain.model.TeTenantRegister;
import com.xueyi.tenant.tenant.mapper.SysEnterpriseStaffMapper;
import com.xueyi.tenant.tenant.mapper.TeTenantMapper;
import com.xueyi.tenant.tenant.service.ITeTenantService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -110,10 +107,12 @@ public class TeTenantController extends BaseController<TeTenantQuery, TeTenantDt
@TenantIgnore(tenantLine = true)
R<SysEnterpriseStaff> staff(@RequestBody SysEnterpriseStaff staff) {
if (staff.getId() != null) {
staffMapper.updateById(staff);
} else {
staffMapper.insert(staff);
SysEnterpriseStaff staffPo = staffMapper.selectById(staff.getId());
if (null != staffPo) {
staffMapper.updateById(staff);
}
}
staffMapper.insert(staff);
return R.ok(staff);
}
/**


불러오는 중...
취소
저장