# Conflicts: # xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/staff/service/impl/DmStaffServiceImpl.javatags/B.2.6.9_20240116_release
@@ -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; | |||
@@ -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; | |||
/** 邀约访问时间 */ | |||
@@ -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; | |||
@@ -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) |
@@ -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); | |||
} |
@@ -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()); | |||
} | |||
}; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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 */ | |||
@@ -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(); | |||
@@ -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); | |||
@@ -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 |
@@ -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") | |||
@@ -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(); | |||
@@ -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("租户列表获取失败"); | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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,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(); | |||
} | |||
} |
@@ -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; | |||
@@ -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()); | |||
@@ -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); | |||
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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) { | |||
@@ -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,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; | |||
@@ -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; | |||
@@ -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); | |||
} | |||
} |
@@ -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,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,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; | |||
/** | |||
@@ -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,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; | |||
/** | |||
@@ -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); | |||
} |
@@ -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; | |||
@@ -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; | |||
@@ -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,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); | |||
} | |||
@@ -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; | |||
@@ -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; | |||
@@ -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); | |||
} | |||
@@ -14,4 +14,6 @@ import com.xueyi.common.datasource.annotation.Isolate; | |||
@Isolate | |||
public interface DmResourcesMapper extends BaseMapper<DmResourcesQuery, DmResourcesDto, DmResourcesPo> { | |||
Long insertOne(DmResourcesPo dmResourcesPo); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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(); | |||
@@ -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("短信发送成功,请注意查收"); | |||
} | |||
/** | |||
* 获取租户访客接待短信模板配置选择框列表 | |||
*/ | |||
@@ -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; | |||
@@ -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){ | |||
@@ -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(); | |||
@@ -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; | |||
} |
@@ -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> { | |||
} |
@@ -113,5 +113,11 @@ public class DmEmpAttendancePo extends TBaseEntity { | |||
'}'; | |||
} | |||
public DmEmpAttendancePo(){ | |||
super(); | |||
this.setWorkDuration(0); | |||
this.setCreateTime(MyDateUtils.currentDateToLocalDateTime()); | |||
this.setUpdateTime(MyDateUtils.currentDateToLocalDateTime()); | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
@@ -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; | |||
} | |||
} |
@@ -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(); | |||
} | |||
@@ -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); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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> { | |||
} |
@@ -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 { | |||
} |
@@ -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> { | |||
} |
@@ -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); | |||
} |
@@ -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> { | |||
} |
@@ -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(){ | |||
@@ -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); | |||
} | |||
} |
@@ -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("发送成功"); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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解码 | |||
@@ -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,6 +1,7 @@ | |||
scalar Long | |||
scalar DateTime | |||
scalar Date | |||
scalar Time | |||
type Query { | |||
@@ -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 | |||
@@ -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 | |||
} |
@@ -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 | |||
} |
@@ -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,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> |
@@ -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); | |||
} | |||
/** | |||