| @@ -39,6 +39,12 @@ | |||
| <artifactId>xueyi-api-tenant</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>io.github.graphql-java</groupId> | |||
| <artifactId>graphql-java-annotations</artifactId> | |||
| <version>21.1</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -30,4 +30,7 @@ public interface RemoteLoginService { | |||
| @GetMapping("/login/inner/loginInfo/{enterpriseName}/{userName}/{password}") | |||
| R<LoginUser> getLoginInfoInner(@PathVariable("enterpriseName") String enterpriseName, @PathVariable("userName") String userName, @PathVariable("password") String password, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping("/login/inner/loginByPhone/{phone}") | |||
| R<LoginUser> getLoginInfoInnerByPhone(@PathVariable("phone") String phone, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| } | |||
| @@ -24,6 +24,11 @@ public class RemoteLoginFallbackFactory implements FallbackFactory<RemoteLoginSe | |||
| public R<LoginUser> getLoginInfoInner(String enterpriseName, String userName, String password, String source) { | |||
| return R.fail("获取登录信息失败:" + throwable.getMessage()); | |||
| } | |||
| @Override | |||
| public R<LoginUser> getLoginInfoInnerByPhone(String phone, String source) { | |||
| return R.fail("获取登录信息失败:" + throwable.getMessage()); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| @@ -77,6 +77,7 @@ public class DmVisitRecordsPo extends TBaseEntity { | |||
| public String toString(){ | |||
| return new StringBuilder("VisitorId: ").append(visitorId).append(", UserId: ").append(userId).append(", VisitDate: ").append(visitDate).append(", VisitTime: ").append(visitTime).append(", Duration: ").append(duration).append(", RecordStatus: ").append(recordStatus).append(", DeptId: ").append(deptId).append(", Num: ").append(num).toString(); | |||
| } | |||
| @@ -3,6 +3,7 @@ package com.xueyi.system.api.digitalmans.domain.po; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import com.xueyi.common.core.annotation.Excel; | |||
| import com.xueyi.common.core.web.tenant.base.TBaseEntity; | |||
| import graphql.annotations.annotationTypes.GraphQLField; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| @@ -30,10 +31,12 @@ public class DmVisitorsPo extends TBaseEntity { | |||
| protected Long roomId; | |||
| /** 访客电话 */ | |||
| @GraphQLField | |||
| @Excel(name = "访客电话") | |||
| protected String phone; | |||
| /** 1:男;2:女 */ | |||
| @GraphQLField | |||
| @Excel(name = "1:男;2:女") | |||
| protected Integer gender; | |||
| @@ -42,10 +45,12 @@ public class DmVisitorsPo extends TBaseEntity { | |||
| protected Integer age; | |||
| /** 访客公司 */ | |||
| @GraphQLField | |||
| @Excel(name = "访客公司") | |||
| protected String visitorCompany; | |||
| /** 访客称呼 */ | |||
| @GraphQLField | |||
| @Excel(name = "访客称呼") | |||
| protected String nickname; | |||
| @@ -54,13 +59,16 @@ public class DmVisitorsPo extends TBaseEntity { | |||
| protected Long deptId; | |||
| /** 访客类型 */ | |||
| @GraphQLField | |||
| @Excel(name = "访客类型") | |||
| protected Long type; | |||
| /** 上传头像 */ | |||
| @GraphQLField | |||
| @Excel(name = "上传头像") | |||
| protected String avatar; | |||
| @GraphQLField | |||
| protected Long resourceId; | |||
| @@ -1,5 +1,6 @@ | |||
| package com.xueyi.system.api.staff.domain.dto; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import lombok.Data; | |||
| /** | |||
| @@ -35,6 +36,21 @@ public class DmVisitCommonDto { | |||
| private String visitorBase64Img; | |||
| public String toSmsJson(String code, String name, String companyName, String companyAddress, String parkInfo){ | |||
| JSONObject json = new JSONObject(); | |||
| json.put("code", code); | |||
| json.put("nickName", this.getVisitorName()); | |||
| json.put("robotName", name); | |||
| json.put("dateTime", this.getVisitDate()); | |||
| json.put("companyName", companyName); | |||
| json.put("companyAddr", companyAddress); | |||
| json.put("receiverName", this.getEmpName()); | |||
| json.put("receiverPhone", this.getEmpTel()); | |||
| json.put("parkInfo", parkInfo); | |||
| return json.toJSONString(); | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return "DmVisitCommonDto{" + | |||
| @@ -1,16 +1,13 @@ | |||
| package com.xueyi.system.api.staff.domain.po; | |||
| import java.util.Date; | |||
| import com.fasterxml.jackson.annotation.JsonFormat; | |||
| import com.xueyi.common.core.web.tenant.base.TBaseEntity; | |||
| import com.xueyi.common.core.annotation.Excel; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| 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 static com.xueyi.common.core.constant.basic.EntityConstants.NAME; | |||
| import java.util.Date; | |||
| /** | |||
| * 人员 持久化对象 | |||
| @@ -95,4 +92,6 @@ public class DmStaffPo extends TBaseEntity { | |||
| @Excel(name = "入职日期") | |||
| protected Date hireDate; | |||
| private Long tenantId; | |||
| } | |||
| @@ -10,3 +10,4 @@ com.xueyi.system.api.log.feign.factory.RemoteLogFallbackFactory | |||
| 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 | |||
| @@ -0,0 +1,16 @@ | |||
| package com.xueyi.tenant.api.tenant.domain.dto; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| /** | |||
| * 租户 数据传输对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class SysStaffDto extends SysStaffPo { | |||
| } | |||
| @@ -0,0 +1,97 @@ | |||
| package com.xueyi.tenant.api.tenant.domain.po; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| 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.util.Date; | |||
| /** | |||
| * 人员 持久化对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| @TableName(value = "dm_staff") | |||
| public class SysStaffPo extends TBaseEntity { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| /** 用户编码 */ | |||
| @Excel(name = "用户编码") | |||
| protected String code; | |||
| /** 用户账号 */ | |||
| @Excel(name = "用户账号") | |||
| protected String userName; | |||
| /** 用户昵称 */ | |||
| @Excel(name = "用户昵称") | |||
| protected String nickName; | |||
| /** 用户类型(00超管用户 01普通用户) */ | |||
| @Excel(name = "用户类型", readConverterExp = "0=0超管用户,0=1普通用户") | |||
| protected String userType; | |||
| /** 手机号码 */ | |||
| @Excel(name = "手机号码") | |||
| protected String phone; | |||
| /** 用户邮箱 */ | |||
| @Excel(name = "用户邮箱") | |||
| protected String email; | |||
| /** 用户性别(0男 1女 2保密) */ | |||
| @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=保密") | |||
| protected String sex; | |||
| /** 头像地址 */ | |||
| @Excel(name = "头像地址") | |||
| protected String avatar; | |||
| /** 个人简介 */ | |||
| @Excel(name = "个人简介") | |||
| protected String profile; | |||
| /** 密码 */ | |||
| @Excel(name = "密码") | |||
| protected String password; | |||
| /** 最后登录IP */ | |||
| @Excel(name = "最后登录IP") | |||
| protected String loginIp; | |||
| /** 最后登录时间 */ | |||
| @Excel(name = "最后登录时间") | |||
| protected Date loginDate; | |||
| /** 备注 */ | |||
| @Excel(name = "备注") | |||
| protected String remark; | |||
| /** 所属组织ID */ | |||
| @Excel(name = "所属组织ID") | |||
| protected Long deptId; | |||
| /** 所属资源ID */ | |||
| @Excel(name = "所属组织ID") | |||
| protected Long resourceId; | |||
| /** 生日日期 */ | |||
| @Excel(name = "生日日期") | |||
| protected Date birthDate; | |||
| /** 入职日期 */ | |||
| @Excel(name = "入职日期") | |||
| protected Date hireDate; | |||
| private Long tenantId; | |||
| } | |||
| @@ -63,4 +63,18 @@ public class TeTenantPo extends BaseEntity { | |||
| @TableField(updateStrategy = FieldStrategy.NEVER) | |||
| protected String isDefault; | |||
| @Override | |||
| public String toString(){ | |||
| return "TeTenantPo{" + | |||
| "strategyId=" + strategyId + | |||
| ", name='" + name + '\'' + | |||
| ", systemName='" + systemName + '\'' + | |||
| ", nick='" + nick + '\'' + | |||
| ", logo='" + logo + '\'' + | |||
| ", nameFrequency=" + nameFrequency + | |||
| ", isLessor='" + isLessor + '\'' + | |||
| ", isDefault='" + isDefault + '\'' + | |||
| '}'; | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| package com.xueyi.tenant.api.tenant.domain.query; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import java.io.Serial; | |||
| /** | |||
| * 租户 数据查询对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class SysStaffQuery extends SysStaffPo { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| } | |||
| @@ -5,6 +5,7 @@ import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.basic.ServiceConstants; | |||
| import com.xueyi.common.core.web.result.R; | |||
| import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| import com.xueyi.tenant.api.tenant.domain.po.TeTenantPo; | |||
| import com.xueyi.tenant.api.tenant.feign.factory.RemoteTenantFallbackFactory; | |||
| import org.springframework.cloud.openfeign.FeignClient; | |||
| @@ -12,6 +13,7 @@ import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestHeader; | |||
| import org.springframework.web.bind.annotation.RequestParam; | |||
| import java.util.List; | |||
| @@ -36,4 +38,11 @@ public interface RemoteTenantService { | |||
| @GetMapping("/tenant/tenant_list") | |||
| R<List<TeTenantDto>> tenantList(); | |||
| @GetMapping("/tenant/one") | |||
| R<TeTenantPo> tenant(@RequestParam ("phone") String phone, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping("/tenant/staff") | |||
| R<SysStaffPo> existStaff(@RequestParam ("phone") String phone, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| } | |||
| @@ -3,6 +3,8 @@ package com.xueyi.tenant.api.tenant.feign.factory; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.xueyi.common.core.web.result.R; | |||
| import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| import com.xueyi.tenant.api.tenant.domain.po.TeTenantPo; | |||
| import com.xueyi.tenant.api.tenant.feign.RemoteTenantService; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.cloud.openfeign.FallbackFactory; | |||
| @@ -34,6 +36,17 @@ public class RemoteTenantFallbackFactory implements FallbackFactory<RemoteTenant | |||
| public R<List<TeTenantDto>> tenantList() { | |||
| return null; | |||
| } | |||
| @Override | |||
| public R<TeTenantPo> tenant(String phone, String source) { | |||
| return R.fail("获取租户失败:" + throwable.getMessage()); | |||
| } | |||
| @Override | |||
| public R<SysStaffPo> existStaff(String phone, String source) { | |||
| return R.fail("验证用户手机号失败:" + throwable.getMessage()); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| @@ -51,6 +51,11 @@ | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-security</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-sms</artifactId> | |||
| </dependency> | |||
| </dependencies> | |||
| @@ -1,24 +1,41 @@ | |||
| package com.xueyi.auth.controller; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.xueyi.auth.form.LoginBody; | |||
| import com.xueyi.auth.form.PhoneLoginBody; | |||
| import com.xueyi.auth.form.RegisterBody; | |||
| import com.xueyi.auth.service.SysLoginService; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.basic.TenantConstants; | |||
| import com.xueyi.common.core.utils.JwtUtil; | |||
| import com.xueyi.common.core.utils.core.ObjectUtil; | |||
| 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.redis.service.RedisService; | |||
| import com.xueyi.common.security.auth.AuthUtil; | |||
| import com.xueyi.common.security.service.TokenService; | |||
| import com.xueyi.common.security.utils.SecurityUtils; | |||
| import com.xueyi.common.sms.configure.SmsProperties; | |||
| import com.xueyi.system.api.model.LoginUser; | |||
| import com.xueyi.system.api.sms.domain.vo.SmsReqEntity; | |||
| import com.xueyi.system.api.sms.feign.RemoteSmsService; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| import com.xueyi.tenant.api.tenant.feign.RemoteTenantService; | |||
| import org.slf4j.Logger; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestParam; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.validation.Valid; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * token 控制 | |||
| @@ -28,12 +45,36 @@ import javax.servlet.http.HttpServletRequest; | |||
| @RestController | |||
| public class TokenController { | |||
| private final Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass()); | |||
| @Autowired | |||
| private TokenService tokenService; | |||
| @Autowired | |||
| private SysLoginService sysLoginService; | |||
| @Autowired | |||
| private RemoteSmsService smsService; | |||
| @Autowired | |||
| private RemoteSmsService remoteSmsService; | |||
| @Autowired | |||
| private SmsProperties smsProperties; | |||
| @Autowired | |||
| private RedisService redisService; | |||
| @Autowired | |||
| private RemoteTenantService tenantService; | |||
| @Autowired | |||
| private RedisTemplate<String, String> redisTemplate; | |||
| private final String REDIS_LOGIN_CODE_PIX = "saas:login:code:"; | |||
| @PostMapping("login") | |||
| public AjaxResult login(@RequestBody LoginBody form) { | |||
| // 用户登录 | |||
| @@ -42,6 +83,25 @@ public class TokenController { | |||
| return AjaxResult.success(tokenService.createToken(userInfo)); | |||
| } | |||
| @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("验证码输入不正确"); | |||
| } | |||
| }*/ | |||
| // 用户手机号验证登录 | |||
| LoginUser userInfo = sysLoginService.loginByPhone(form.getPhone()); | |||
| if (null == userInfo) { | |||
| return AjaxResult.error("手机号不正确,清查验"); | |||
| } | |||
| // 获取登录token | |||
| return AjaxResult.success(tokenService.createToken(userInfo)); | |||
| } | |||
| @DeleteMapping("logout") | |||
| public AjaxResult logout(HttpServletRequest request) { | |||
| String token = SecurityUtils.getToken(request); | |||
| @@ -76,4 +136,35 @@ public class TokenController { | |||
| sysLoginService.register(registerBody); | |||
| return AjaxResult.success(); | |||
| } | |||
| @GetMapping("validCode") | |||
| public R validCode(@RequestParam String phone) { | |||
| R<SysStaffPo> staff = tenantService.existStaff(phone, SecurityConstants.INNER); | |||
| if (staff.getData() == null) { | |||
| return R.fail("手机号不存在,请查验"); | |||
| } | |||
| SmsReqEntity smsReqEntity = new SmsReqEntity(); | |||
| smsReqEntity.setPhone(phone); | |||
| String str = StrUtil.generateCode(); | |||
| if (StringUtils.isEmpty(phone)){ | |||
| return R.fail("手机号为空"); | |||
| } else { | |||
| if (redisService.hasKey(REDIS_LOGIN_CODE_PIX + phone)) { | |||
| return R.fail("之前请求的验证码并未失效,请查看短信或稍后重试"); | |||
| } else { | |||
| redisTemplate.opsForValue().setIfAbsent(REDIS_LOGIN_CODE_PIX + phone, str, 5, TimeUnit.MINUTES); | |||
| } | |||
| smsReqEntity.setTemplate(smsProperties.getCodeTemplate()); | |||
| JSONObject map = new JSONObject(); | |||
| map.put("code", str); | |||
| smsReqEntity.setDataMap(map.toJSONString()); | |||
| log.info("发送验证码成功,手机号:{},验证码:{}, sendReq:{}", phone, str, smsReqEntity.toJson().toJSONString()); | |||
| remoteSmsService.sendSms(smsReqEntity); | |||
| } | |||
| return R.ok("验证码发送成功,请查看短信"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| package com.xueyi.auth.form; | |||
| import lombok.Data; | |||
| import javax.validation.constraints.NotEmpty; | |||
| /** | |||
| * 用户登录对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| public class PhoneLoginBody { | |||
| @NotEmpty(message = "手机号不能为空") | |||
| private String phone; | |||
| private String code; | |||
| } | |||
| @@ -29,6 +29,7 @@ import org.springframework.stereotype.Component; | |||
| @Component | |||
| public class SysLoginService { | |||
| @Autowired | |||
| private RemoteLogService remoteLogService; | |||
| @@ -165,4 +166,15 @@ public class SysLoginService { | |||
| } | |||
| remoteLogService.saveLoginInfo(loginInfo, enterpriseId, sourceName, SecurityConstants.INNER); | |||
| } | |||
| public LoginUser loginByPhone(String phone) { | |||
| R<LoginUser> loginInfoResult = remoteLoginService.getLoginInfoInnerByPhone(phone, SecurityConstants.INNER); | |||
| if (ObjectUtil.isNull(loginInfoResult.getData())) { | |||
| AjaxResult.warn("手机号可能输错,请查证后重试!"); | |||
| } | |||
| return loginInfoResult.getData(); | |||
| } | |||
| } | |||
| @@ -27,3 +27,4 @@ spring: | |||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||
| - application-secret-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||
| - application-datasource-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||
| - ali-sms.yml | |||
| @@ -0,0 +1 @@ | |||
| com.xueyi.common.web.entity.domain.mapper.DeviceTenantMergeMapper | |||
| @@ -20,4 +20,32 @@ public class NumberUtil extends cn.hutool.core.util.NumberUtil implements Number | |||
| return number == null ? 0 : number; | |||
| } | |||
| /** | |||
| * @Author yangkai | |||
| * @Description 将int类型的数据转化成X小时Y分钟的形式 | |||
| * @Date 2023/9/21 | |||
| * @Param | |||
| * @return | |||
| **/ | |||
| public static String convertMinutesToHoursMinutes(int minutes) { | |||
| if (minutes < 0) { | |||
| throw new IllegalArgumentException("分钟数不能为负数"); | |||
| } | |||
| int hours = minutes / 60; | |||
| int remainingMinutes = minutes % 60; | |||
| String hourMin = String.format("%d小时%d分钟", hours, remainingMinutes); | |||
| //如果小时数为0,则不显示"小时" | |||
| if (hours == 0) { | |||
| hourMin = String.format("%d分钟", remainingMinutes); | |||
| } | |||
| //如果分钟数为0,则不显示"分钟" | |||
| if (remainingMinutes == 0) { | |||
| hourMin = String.format("%d小时", hours); | |||
| } | |||
| return hourMin; | |||
| } | |||
| } | |||
| @@ -1,9 +1,29 @@ | |||
| package com.xueyi.common.core.utils.core; | |||
| import java.lang.annotation.Annotation; | |||
| import java.lang.reflect.Field; | |||
| import java.util.HashSet; | |||
| import java.util.Set; | |||
| /** | |||
| * 对象工具类 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public class ObjectUtil extends cn.hutool.core.util.ObjectUtil { | |||
| public static Set<String> findAnnotatedFields(Class<?> clazz, Class<? extends Annotation> annotationClass) { | |||
| Set<String> annotatedFields = new HashSet<String>(); | |||
| for (Field field : clazz.getDeclaredFields()) { | |||
| if (field.isAnnotationPresent(annotationClass)) { | |||
| annotatedFields.add(field.getName()); | |||
| } | |||
| } | |||
| return annotatedFields; | |||
| } | |||
| } | |||
| @@ -190,4 +190,10 @@ public class StrUtil extends cn.hutool.core.util.StrUtil implements StrPool { | |||
| return result.toString(); | |||
| } | |||
| public static String generateCode() { | |||
| String timeStr = String.valueOf(System.currentTimeMillis()); | |||
| return timeStr.substring(timeStr.length() - 4 ); | |||
| } | |||
| } | |||
| @@ -106,6 +106,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| Map<String, Object> rspMap = new HashMap<>(); | |||
| rspMap.put("access_token", JwtUtil.createToken(claimsMap)); | |||
| rspMap.put("expires_in", getTacitExpireTime()); | |||
| rspMap.put("tenant_id", enterpriseId); | |||
| return rspMap; | |||
| } | |||
| @@ -141,6 +142,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| return redisService.getCacheMapValue(getTokenKey(userKey), SecurityConstants.BaseSecurity.ENTERPRISE.getCode()); | |||
| } | |||
| } catch (Exception ignored) { | |||
| System.err.println(ignored.getMessage());; | |||
| } | |||
| return null; | |||
| } | |||
| @@ -177,6 +179,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| return redisService.getCacheMapValue(getTokenKey(userKey), SecurityConstants.BaseSecurity.USER.getCode()); | |||
| } | |||
| } catch (Exception ignored) { | |||
| System.err.println(ignored.getMessage());; | |||
| } | |||
| return null; | |||
| } | |||
| @@ -213,6 +216,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| return redisService.getCacheMapValue(getTokenKey(userKey), SecurityConstants.BaseSecurity.LOGIN_USER.getCode()); | |||
| } | |||
| } catch (Exception ignored) { | |||
| System.err.println(ignored.getMessage());; | |||
| } | |||
| return null; | |||
| } | |||
| @@ -260,6 +264,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| return redisService.getCacheMapValue(getTokenKey(userKey), SecurityConstants.BaseSecurity.SOURCE.getCode()); | |||
| } | |||
| } catch (Exception ignored) { | |||
| System.err.println(ignored.getMessage());; | |||
| } | |||
| return null; | |||
| } | |||
| @@ -297,6 +302,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| return redisService.getCacheMapValue(getTokenKey(userKey), SecurityConstants.BaseSecurity.EXPIRE_TIME.getCode()); | |||
| } | |||
| } catch (Exception ignored) { | |||
| System.err.println(ignored.getMessage());; | |||
| } | |||
| return null; | |||
| } | |||
| @@ -329,7 +335,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| */ | |||
| public void refreshToken(HttpServletRequest request) { | |||
| String token = SecurityUtils.getToken(request); | |||
| refreshToken(SecurityUtils.getToken(request)); | |||
| refreshToken(token); | |||
| } | |||
| /** | |||
| @@ -4,9 +4,6 @@ import com.xueyi.common.redis.service.RedisService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.HashSet; | |||
| import java.util.Set; | |||
| /** | |||
| * spring sms 工具类 | |||
| * | |||
| @@ -19,6 +16,7 @@ public class SmsService { | |||
| @Autowired | |||
| private RedisService redisService; | |||
| /** | |||
| * @Author yangkai | |||
| * @Description //发送验证码,取时间戳后四位 | |||
| @@ -27,7 +25,6 @@ public class SmsService { | |||
| * @return | |||
| **/ | |||
| public String sendCode(){ | |||
| Set<String> codes = new HashSet<>(); | |||
| String code = ""; | |||
| //确保不重复 | |||
| while(true) { | |||
| @@ -7,6 +7,7 @@ import java.text.DecimalFormat; | |||
| import java.text.ParseException; | |||
| import java.text.ParsePosition; | |||
| import java.text.SimpleDateFormat; | |||
| import java.time.LocalDate; | |||
| import java.time.LocalDateTime; | |||
| import java.time.LocalTime; | |||
| import java.time.ZoneId; | |||
| @@ -16,334 +17,358 @@ import java.util.GregorianCalendar; | |||
| import java.util.List; | |||
| public class DateUtils extends org.apache.commons.lang.time.DateUtils { | |||
| public DateUtils() { | |||
| } | |||
| public static Date getPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num - 1)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFixedPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayFirst(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getPageDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -1); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFirstDayOfMonth(Date date) { | |||
| new SimpleDateFormat("yyyy-MM-dd "); | |||
| GregorianCalendar gcLast = (GregorianCalendar)Calendar.getInstance(); | |||
| gcLast.setTime(date); | |||
| gcLast.set(Calendar.DAY_OF_MONTH, 1); | |||
| return gcLast.getTime(); | |||
| } | |||
| public static Date getLastDayOfMonth(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date getAttendanceTime(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -2); | |||
| calendar.set(11, 23); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String getStartTime() { | |||
| Date dNow = new Date(); | |||
| new Date(); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(dNow); | |||
| calendar.add(5, -1); | |||
| Date dBefore = calendar.getTime(); | |||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); | |||
| return sdf.format(dBefore); | |||
| } | |||
| /*/** | |||
| * @Author yangkai | |||
| * @Description 根据字符串日期返回星期几 | |||
| * @Param [datetime] | |||
| * @return java.lang.String | |||
| **/ | |||
| public static String dateToWeek(String datetime) { | |||
| SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); | |||
| String[] weekDays = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; | |||
| Calendar cal = Calendar.getInstance(); | |||
| Date datet = null; | |||
| try { | |||
| datet = f.parse(datetime); | |||
| cal.setTime(datet); | |||
| } catch (ParseException var6) { | |||
| var6.printStackTrace(); | |||
| } | |||
| int w = cal.get(7) - 1; | |||
| if (w < 0) { | |||
| w = 0; | |||
| } | |||
| return weekDays[w]; | |||
| } | |||
| public static String getDatePoor(Date endDate, Date nowDate) { | |||
| long nd = 86400000L; | |||
| long nh = 3600000L; | |||
| long nm = 60000L; | |||
| long diff = endDate.getTime() - nowDate.getTime(); | |||
| long day = diff / nd; | |||
| long hour = diff % nd / nh; | |||
| long min = diff % nd % nh / nm; | |||
| return day + ":" + hour; | |||
| } | |||
| /** | |||
| * 1 2 3 4 5 6 7 | |||
| * 日 一 二 三 四 五 六 | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static Integer getDayOfWeek(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| return calendar.get(Calendar.DAY_OF_WEEK); | |||
| } | |||
| public static List<String> generateNearlyDateString(Date currentDate, Integer nearlyDays) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(currentDate); | |||
| List<String> dateStringList = Lists.newLinkedList(); | |||
| for(int i = 0; i < nearlyDays; ++i) { | |||
| calendar.add(5, i == 0 ? 0 : -1); | |||
| dateStringList.add(formatDate(calendar.getTime(), "yyyy-MM-dd")); | |||
| } | |||
| return dateStringList; | |||
| } | |||
| public static String dateDiff(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| String hoursStr = hours + "h"; | |||
| String minutesStr = minutes == 0 ? "" : minutes + "m"; | |||
| return hoursStr + minutesStr; | |||
| } else { | |||
| return "0h"; | |||
| } | |||
| } | |||
| public static Integer dateDiffMin(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours * 60 + minutes; | |||
| } else { | |||
| return 0; | |||
| } | |||
| } | |||
| public static String intToHourMin(Integer minuteDiff) { | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours+"小时"+ minutes+"分"; | |||
| } | |||
| public static String formatDate(Date date, String pattern) { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(pattern); | |||
| return sdf.format(date); | |||
| } | |||
| public static Date praseStringToDate(String dateStr) throws ParseException { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(); | |||
| return sdf.parse(dateStr); | |||
| } | |||
| public static Date parseLongToDate(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date parseLongToDate(String dateLong) throws ParseException { | |||
| BigDecimal number = new BigDecimal(dateLong); | |||
| return parseLongToDate(number.doubleValue()); | |||
| } | |||
| public static Date parseLongToDate(Double dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| DecimalFormat df = new DecimalFormat("#"); // 创建DecimalFormat对象 | |||
| String str = df.format(dateLong); | |||
| if (str.indexOf(".")>-1) { | |||
| str = str.replace(".",""); | |||
| } | |||
| str = str.substring(0,13); | |||
| BigDecimal number = new BigDecimal(str); | |||
| calendar.setTimeInMillis(number.longValue()); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String praseLongToDateString(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| Date date = calendar.getTime(); | |||
| return formatDate(date, "yyyy-MM-dd HH:mm:ss"); | |||
| } | |||
| public static String getMillsSecondsDouble() { | |||
| Long cutime = System.currentTimeMillis(); | |||
| String cutimeStr = String.valueOf(cutime); | |||
| BigDecimal d = new BigDecimal(cutimeStr.substring(0, 10) + "." + cutimeStr.substring(10)); | |||
| return d.stripTrailingZeros().toPlainString(); | |||
| } | |||
| /** | |||
| * | |||
| * @param time 2018-07-06 19:35:23 | |||
| * @param pattern yyyy-MM-dd HH:mm:ss | |||
| * @return | |||
| */ | |||
| public static Date parseStrToDate(String time, String pattern) { | |||
| SimpleDateFormat formatter = new SimpleDateFormat(pattern); | |||
| ParsePosition pos = new ParsePosition(0); | |||
| return formatter.parse(time, pos); | |||
| } | |||
| //形如yyyy-MM-dd格式的时间串,赠加或减少几天 | |||
| //如2022-06-06 增加一天 返回 2022-06-07 | |||
| public static String dateStrAdd(String dateStr, int addDays){ | |||
| Date date1 = DateUtils.parseStrToDate(dateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.addDays(date1, addDays); | |||
| String dateStr2 = DateUtils.formatDate(date2, "yyyy-MM-dd"); | |||
| return dateStr2; | |||
| } | |||
| public static int dateStrDiff(String startDateStr, String endDateStr) { | |||
| Date date1 = DateUtils.parseStrToDate(startDateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.parseStrToDate(endDateStr, "yyyy-MM-dd"); | |||
| Calendar cal1 = Calendar.getInstance(); | |||
| cal1.setTime(date1); | |||
| Calendar cal2 = Calendar.getInstance(); | |||
| cal2.setTime(date2); | |||
| int day1= cal1.get(Calendar.DAY_OF_YEAR); | |||
| int day2 = cal2.get(Calendar.DAY_OF_YEAR); | |||
| int year1 = cal1.get(Calendar.YEAR); | |||
| int year2 = cal2.get(Calendar.YEAR); | |||
| if (year1 != year2) {//同一年 | |||
| int timeDistance = 0; | |||
| for (int i = year1; i < year2; i++) { | |||
| if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) //闰年 | |||
| { | |||
| timeDistance += 366; | |||
| } else { | |||
| timeDistance += 365; | |||
| } | |||
| } | |||
| return timeDistance + (day2 - day1); | |||
| } else {// 不同年 | |||
| return day2 - day1; | |||
| } | |||
| } | |||
| public static LocalDateTime currentDateToLocalDateTime(){ | |||
| Date todayDate = new Date(); | |||
| return dateToLocalDateTime(todayDate); | |||
| } | |||
| public static LocalDateTime dateToLocalDateTime(Date date){ | |||
| LocalDateTime ldt = date.toInstant() | |||
| .atZone( ZoneId.systemDefault() ) | |||
| .toLocalDateTime(); | |||
| return ldt; | |||
| } | |||
| public static String isAmPm(){ | |||
| //判断当前时间是上午还是下午,上午返回am,下午返回pm | |||
| LocalTime currentTime = LocalTime.now(); | |||
| if (currentTime.isBefore(LocalTime.NOON)) { | |||
| return "am"; | |||
| } else { | |||
| return "pm"; | |||
| } | |||
| } | |||
| public DateUtils() { | |||
| } | |||
| public static Date getPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num - 1)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFixedPushForwardDate(Date date, Integer num) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -(num)); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayFirst(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 0); | |||
| calendar.set(12, 0); | |||
| calendar.set(13, 0); | |||
| calendar.set(14, 0); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getOfDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getPageDayLast(Date date) { | |||
| if (date == null) { | |||
| return null; | |||
| } else { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -1); | |||
| calendar.set(11, 23); | |||
| calendar.set(12, 59); | |||
| calendar.set(13, 59); | |||
| calendar.set(14, 999); | |||
| return calendar.getTime(); | |||
| } | |||
| } | |||
| public static Date getFirstDayOfMonth(Date date) { | |||
| new SimpleDateFormat("yyyy-MM-dd "); | |||
| GregorianCalendar gcLast = (GregorianCalendar) Calendar.getInstance(); | |||
| gcLast.setTime(date); | |||
| gcLast.set(Calendar.DAY_OF_MONTH, 1); | |||
| return gcLast.getTime(); | |||
| } | |||
| public static Date getLastDayOfMonth(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date getAttendanceTime(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| calendar.add(5, -2); | |||
| calendar.set(11, 23); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String getStartTime() { | |||
| Date dNow = new Date(); | |||
| new Date(); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(dNow); | |||
| calendar.add(5, -1); | |||
| Date dBefore = calendar.getTime(); | |||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); | |||
| return sdf.format(dBefore); | |||
| } | |||
| /*/** | |||
| * @Author yangkai | |||
| * @Description 根据字符串日期返回星期几 | |||
| * @Param [datetime] | |||
| * @return java.lang.String | |||
| **/ | |||
| public static String dateToWeek(String datetime) { | |||
| SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); | |||
| String[] weekDays = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; | |||
| Calendar cal = Calendar.getInstance(); | |||
| Date datet = null; | |||
| try { | |||
| datet = f.parse(datetime); | |||
| cal.setTime(datet); | |||
| } catch (ParseException var6) { | |||
| var6.printStackTrace(); | |||
| } | |||
| int w = cal.get(7) - 1; | |||
| if (w < 0) { | |||
| w = 0; | |||
| } | |||
| return weekDays[w]; | |||
| } | |||
| public static String getDatePoor(Date endDate, Date nowDate) { | |||
| long nd = 86400000L; | |||
| long nh = 3600000L; | |||
| long nm = 60000L; | |||
| long diff = endDate.getTime() - nowDate.getTime(); | |||
| long day = diff / nd; | |||
| long hour = diff % nd / nh; | |||
| long min = diff % nd % nh / nm; | |||
| return day + ":" + hour; | |||
| } | |||
| /** | |||
| * 1 2 3 4 5 6 7 | |||
| * 日 一 二 三 四 五 六 | |||
| * | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static Integer getDayOfWeek(Date date) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(date); | |||
| return calendar.get(Calendar.DAY_OF_WEEK); | |||
| } | |||
| public static List<String> generateNearlyDateString(Date currentDate, Integer nearlyDays) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTime(currentDate); | |||
| List<String> dateStringList = Lists.newLinkedList(); | |||
| for (int i = 0; i < nearlyDays; ++i) { | |||
| calendar.add(5, i == 0 ? 0 : -1); | |||
| dateStringList.add(formatDate(calendar.getTime(), "yyyy-MM-dd")); | |||
| } | |||
| return dateStringList; | |||
| } | |||
| public static String dateDiff(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| String hoursStr = hours + "h"; | |||
| String minutesStr = minutes == 0 ? "" : minutes + "m"; | |||
| return hoursStr + minutesStr; | |||
| } else { | |||
| return "0h"; | |||
| } | |||
| } | |||
| public static Integer dateDiffMin(Date startDate, Date endDate) { | |||
| if (null != startDate && null != endDate) { | |||
| Long mills = endDate.getTime() - startDate.getTime(); | |||
| Integer minuteDiff = mills.intValue() / '\uea60'; | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours * 60 + minutes; | |||
| } else { | |||
| return 0; | |||
| } | |||
| } | |||
| public static String intToHourMin(Integer minuteDiff) { | |||
| Integer hours = minuteDiff / 60; | |||
| Integer minutes = minuteDiff % 60; | |||
| return hours + "小时" + minutes + "分"; | |||
| } | |||
| public static String formatDate(Date date, String pattern) { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(pattern); | |||
| return sdf.format(date); | |||
| } | |||
| public static Date praseStringToDate(String dateStr) throws ParseException { | |||
| SimpleDateFormat sdf = new SimpleDateFormat(); | |||
| return sdf.parse(dateStr); | |||
| } | |||
| public static Date parseLongToDate(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| return calendar.getTime(); | |||
| } | |||
| public static Date parseLongToDate(String dateLong) throws ParseException { | |||
| BigDecimal number = new BigDecimal(dateLong); | |||
| return parseLongToDate(number.doubleValue()); | |||
| } | |||
| public static Date parseLongToDate(Double dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| DecimalFormat df = new DecimalFormat("#"); // 创建DecimalFormat对象 | |||
| String str = df.format(dateLong); | |||
| if (str.indexOf(".") > -1) { | |||
| str = str.replace(".", ""); | |||
| } | |||
| str = str.substring(0, 13); | |||
| BigDecimal number = new BigDecimal(str); | |||
| calendar.setTimeInMillis(number.longValue()); | |||
| return calendar.getTime(); | |||
| } | |||
| public static String praseLongToDateString(Long dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(dateLong); | |||
| Date date = calendar.getTime(); | |||
| return formatDate(date, "yyyy-MM-dd HH:mm:ss"); | |||
| } | |||
| public static String getMillsSecondsDouble() { | |||
| Long cutime = System.currentTimeMillis(); | |||
| String cutimeStr = String.valueOf(cutime); | |||
| BigDecimal d = new BigDecimal(cutimeStr.substring(0, 10) + "." + cutimeStr.substring(10)); | |||
| return d.stripTrailingZeros().toPlainString(); | |||
| } | |||
| /** | |||
| * @param time 2018-07-06 19:35:23 | |||
| * @param pattern yyyy-MM-dd HH:mm:ss | |||
| * @return | |||
| */ | |||
| public static Date parseStrToDate(String time, String pattern) { | |||
| SimpleDateFormat formatter = new SimpleDateFormat(pattern); | |||
| ParsePosition pos = new ParsePosition(0); | |||
| return formatter.parse(time, pos); | |||
| } | |||
| //形如yyyy-MM-dd格式的时间串,赠加或减少几天 | |||
| //如2022-06-06 增加一天 返回 2022-06-07 | |||
| public static String dateStrAdd(String dateStr, int addDays) { | |||
| Date date1 = DateUtils.parseStrToDate(dateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.addDays(date1, addDays); | |||
| String dateStr2 = DateUtils.formatDate(date2, "yyyy-MM-dd"); | |||
| return dateStr2; | |||
| } | |||
| public static int dateStrDiff(String startDateStr, String endDateStr) { | |||
| Date date1 = DateUtils.parseStrToDate(startDateStr, "yyyy-MM-dd"); | |||
| Date date2 = DateUtils.parseStrToDate(endDateStr, "yyyy-MM-dd"); | |||
| Calendar cal1 = Calendar.getInstance(); | |||
| cal1.setTime(date1); | |||
| Calendar cal2 = Calendar.getInstance(); | |||
| cal2.setTime(date2); | |||
| int day1 = cal1.get(Calendar.DAY_OF_YEAR); | |||
| int day2 = cal2.get(Calendar.DAY_OF_YEAR); | |||
| int year1 = cal1.get(Calendar.YEAR); | |||
| int year2 = cal2.get(Calendar.YEAR); | |||
| if (year1 != year2) {//同一年 | |||
| int timeDistance = 0; | |||
| for (int i = year1; i < year2; i++) { | |||
| if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) //闰年 | |||
| { | |||
| timeDistance += 366; | |||
| } else { | |||
| timeDistance += 365; | |||
| } | |||
| } | |||
| return timeDistance + (day2 - day1); | |||
| } else {// 不同年 | |||
| return day2 - day1; | |||
| } | |||
| } | |||
| public static LocalDateTime currentDateToLocalDateTime() { | |||
| Date todayDate = new Date(); | |||
| return dateToLocalDateTime(todayDate); | |||
| } | |||
| public static LocalDateTime dateToLocalDateTime(Date date) { | |||
| LocalDateTime ldt = date.toInstant() | |||
| .atZone(ZoneId.systemDefault()) | |||
| .toLocalDateTime(); | |||
| return ldt; | |||
| } | |||
| public static String isAmPm() { | |||
| //判断当前时间是上午还是下午,上午返回am,下午返回pm | |||
| LocalTime currentTime = LocalTime.now(); | |||
| if (currentTime.isBefore(LocalTime.NOON)) { | |||
| return "am"; | |||
| } else { | |||
| return "pm"; | |||
| } | |||
| } | |||
| public static String getChineseWeek(Date date) { | |||
| int week = LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(date)).getDayOfWeek().getValue(); | |||
| switch (week) { | |||
| case 1: | |||
| return "周一"; | |||
| case 2: | |||
| return "周二"; | |||
| case 3: | |||
| return "周三"; | |||
| case 4: | |||
| return "周四"; | |||
| case 5: | |||
| return "周五"; | |||
| case 6: | |||
| return "周六"; | |||
| case 7: | |||
| return "周日"; | |||
| default: | |||
| return ""; | |||
| } | |||
| } | |||
| } | |||
| @@ -137,6 +137,21 @@ | |||
| <version>1.1.1</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.graphql-java</groupId> | |||
| <artifactId>graphql-java</artifactId> | |||
| <version>11.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.alibaba</groupId> | |||
| <artifactId>easyexcel</artifactId> | |||
| <version>3.3.3</version> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| @@ -1,6 +1,7 @@ | |||
| package com.xueyi.system.authority.controller; | |||
| 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.CollUtil; | |||
| import com.xueyi.common.core.utils.core.ObjectUtil; | |||
| @@ -14,6 +15,8 @@ import com.xueyi.system.api.model.Source; | |||
| import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto; | |||
| import com.xueyi.system.api.organize.domain.dto.SysUserDto; | |||
| import com.xueyi.system.authority.service.ISysLoginService; | |||
| import com.xueyi.tenant.api.tenant.domain.po.TeTenantPo; | |||
| import com.xueyi.tenant.api.tenant.feign.RemoteTenantService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| @@ -92,4 +95,69 @@ public class SysLoginController extends BasisController { | |||
| loginUser.setRouteURL(routeMap); | |||
| return R.ok(loginUser); | |||
| } | |||
| @Autowired | |||
| RemoteTenantService tenantService; | |||
| /** | |||
| * 获取登录信息 | 内部调用, 手机号登录 | |||
| */ | |||
| @InnerAuth | |||
| @GetMapping("/inner/loginByPhone/{phone}") | |||
| public R<LoginUser> getLoginInfoByMobile(@PathVariable("phone") String phone) { | |||
| R<TeTenantPo> po = tenantService.tenant(phone, SecurityConstants.INNER); | |||
| if (po.getData() == null) | |||
| return R.fail("指定手机号不存在记录"); | |||
| SysEnterpriseDto enterprise = loginService.loginByEnterpriseName(po.getData().getName()); | |||
| // 不存在直接返回空数据 | 与网络调用错误区分 | |||
| if (ObjectUtil.isNull(enterprise)) | |||
| return R.ok(null, "企业账号不存在"); | |||
| SecurityContextHolder.setEnterpriseId(enterprise.getId().toString()); | |||
| SecurityContextHolder.setIsLessor(enterprise.getIsLessor()); | |||
| Source source = SourceUtil.getSourceCache(enterprise.getStrategyId()); | |||
| // 不存在直接返回空数据 | 与网络调用错误区分 | |||
| if (ObjectUtil.isNull(source)) | |||
| return R.ok(null, "数据源不存在"); | |||
| SecurityContextHolder.setSourceName(source.getMaster()); | |||
| LoginUser loginUser = new LoginUser(); | |||
| loginUser.setEnterprise(enterprise); | |||
| loginUser.setEnterpriseId(enterprise.getId()); | |||
| loginUser.setEnterpriseName(enterprise.getName()); | |||
| loginUser.setIsLessor(enterprise.getIsLessor()); | |||
| loginUser.setSource(source); | |||
| loginUser.setSourceName(source.getMaster()); | |||
| SysUserDto user = loginService.loginByStaff(phone); | |||
| if (ObjectUtil.isNull(user)) | |||
| return R.ok(null, "用户账号不存在"); | |||
| SecurityContextHolder.setUserType(user.getUserType()); | |||
| // 角色权限标识 | |||
| Set<String> roles = loginService.getRolePermission(user.getRoles(), user.getUserType()); | |||
| // 角色Id集合 | |||
| Set<Long> roleIds = CollUtil.isNotEmpty(user.getRoles()) | |||
| ? user.getRoles().stream().map(SysRoleDto::getId).collect(Collectors.toSet()) | |||
| : new HashSet<>(); | |||
| // 菜单权限标识 | |||
| Set<String> permissions = loginService.getMenuPermission(roleIds, user.getUserType()); | |||
| // 权限范围 | |||
| DataScope dataScope = loginService.getDataScope(user.getRoles(), user); | |||
| dataScope.setRoles(roles); | |||
| dataScope.setRoleIds(roleIds); | |||
| dataScope.setPermissions(permissions); | |||
| // 路由路径集合 | |||
| Map<String, String> routeMap = loginService.getMenuRouteMap(roleIds, user.getUserType()); | |||
| loginUser.setUser(user); | |||
| loginUser.setUserId(user.getId()); | |||
| loginUser.setUserName(user.getUserName()); | |||
| loginUser.setUserType(user.getUserType()); | |||
| loginUser.setScope(dataScope); | |||
| loginUser.setRouteURL(routeMap); | |||
| return R.ok(loginUser); | |||
| } | |||
| } | |||
| @@ -68,4 +68,6 @@ public interface ISysLoginService { | |||
| * @return 路由路径集合 | |||
| */ | |||
| Map<String, String> getMenuRouteMap(Set<Long> roleIds, String userType); | |||
| SysUserDto loginByStaff(String phone); | |||
| } | |||
| @@ -1,17 +1,28 @@ | |||
| package com.xueyi.system.authority.service.impl; | |||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
| import com.xueyi.common.core.constant.basic.SqlConstants; | |||
| import com.xueyi.common.core.constant.system.AuthorityConstants; | |||
| import com.xueyi.common.core.utils.core.StrUtil; | |||
| import com.xueyi.common.security.utils.SecurityUtils; | |||
| import com.xueyi.common.web.entity.domain.SqlField; | |||
| import com.xueyi.system.api.authority.domain.dto.SysRoleDto; | |||
| import com.xueyi.system.api.model.DataScope; | |||
| import com.xueyi.system.api.organize.domain.dto.SysDeptDto; | |||
| import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto; | |||
| import com.xueyi.system.api.organize.domain.dto.SysPostDto; | |||
| import com.xueyi.system.api.organize.domain.dto.SysUserDto; | |||
| import com.xueyi.system.api.organize.domain.model.SysUserConverter; | |||
| import com.xueyi.system.api.staff.domain.po.DmStaffPo; | |||
| import com.xueyi.system.authority.service.ISysLoginService; | |||
| import com.xueyi.system.authority.service.ISysMenuService; | |||
| import com.xueyi.system.organize.service.*; | |||
| import com.xueyi.system.organize.mapper.SysUserMapper; | |||
| import com.xueyi.system.organize.service.ISysDeptService; | |||
| import com.xueyi.system.organize.service.ISysEnterpriseService; | |||
| import com.xueyi.system.organize.service.ISysOrganizeService; | |||
| import com.xueyi.system.organize.service.ISysPostService; | |||
| import com.xueyi.system.organize.service.ISysUserService; | |||
| import com.xueyi.system.staff.mapper.DmStaffMapper; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| @@ -44,6 +55,9 @@ public class SysLoginServiceImpl implements ISysLoginService { | |||
| @Autowired | |||
| ISysMenuService menuService; | |||
| @Autowired | |||
| DmStaffMapper dmStaffMapper; | |||
| @Autowired | |||
| private ISysOrganizeService organizeService; | |||
| @@ -220,4 +234,21 @@ public class SysLoginServiceImpl implements ISysLoginService { | |||
| ? menuService.getRouteMap() | |||
| : menuService.getRouteMap(roleIds); | |||
| } | |||
| @Autowired | |||
| SysUserMapper userMapper; | |||
| @Autowired | |||
| SysUserConverter sysUserConverter; | |||
| @Override | |||
| public SysUserDto loginByStaff(String phone) { | |||
| DmStaffPo po = dmStaffMapper.selectOne(Wrappers.<DmStaffPo>query().lambda().eq(DmStaffPo::getPhone, phone).last(SqlConstants.LIMIT_ONE)); | |||
| if (po == null) { | |||
| return null; | |||
| } | |||
| SqlField field = new SqlField(SqlConstants.OperateType.EQ, "tenant_id", po.getTenantId()); | |||
| SysUserDto dto = sysUserConverter.mapperDto(userMapper.selectByField(field)) ; | |||
| return dto; | |||
| } | |||
| } | |||
| @@ -4,7 +4,11 @@ import com.xueyi.common.web.entity.service.IBaseService; | |||
| import com.xueyi.system.common.domain.dto.DmHolidayDto; | |||
| import com.xueyi.system.common.domain.query.DmHolidayQuery; | |||
| import java.util.Date; | |||
| public interface IDmHolidayService extends IBaseService<DmHolidayQuery, DmHolidayDto> { | |||
| DmHolidayDto getTodayHoliday(); | |||
| DmHolidayDto isHoliday(Date date); | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| 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.common.domain.query.DmHolidayQuery; | |||
| @@ -8,14 +9,20 @@ import com.xueyi.system.common.service.IDmHolidayService; | |||
| import org.springframework.stereotype.Service; | |||
| import java.time.LocalDate; | |||
| import java.util.Date; | |||
| @Service | |||
| public class IDmHolidayServiceImpl extends BaseServiceImpl<DmHolidayQuery, DmHolidayDto, IDmHolidayManager> implements IDmHolidayService { | |||
| @Override | |||
| public DmHolidayDto getTodayHoliday() { | |||
| return isHoliday(new Date()); | |||
| } | |||
| @Override | |||
| public DmHolidayDto isHoliday(Date date) { | |||
| DmHolidayQuery query = new DmHolidayQuery(); | |||
| query.setDate(LocalDate.now()); | |||
| query.setDate(LocalDateTimeUtil.of(date).toLocalDate()); | |||
| DmHolidayDto dto = baseManager.selectTodayHoliday(query); | |||
| if (dto != null) { | |||
| return dto; | |||
| @@ -1,8 +1,17 @@ | |||
| package com.xueyi.system.staff.controller; | |||
| import com.alibaba.excel.EasyExcel; | |||
| import com.alibaba.excel.ExcelWriter; | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.util.BooleanUtils; | |||
| import com.alibaba.excel.write.handler.CellWriteHandler; | |||
| import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; | |||
| import com.alibaba.excel.write.metadata.WriteSheet; | |||
| import com.alibaba.excel.write.metadata.style.WriteCellStyle; | |||
| import com.alibaba.excel.write.metadata.style.WriteFont; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.xueyi.common.core.utils.core.StrUtil; | |||
| import com.xueyi.common.core.utils.poi.ExcelUtil; | |||
| import com.xueyi.common.core.utils.core.ObjectUtil; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.validate.V_A; | |||
| import com.xueyi.common.core.web.validate.V_E; | |||
| @@ -11,7 +20,6 @@ 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.common.web.utils.DateUtils; | |||
| import com.xueyi.system.api.organize.domain.po.SysDeptPo; | |||
| import com.xueyi.system.organize.mapper.SysDeptMapper; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.model.DmEmpAttendanceConverter; | |||
| @@ -19,15 +27,30 @@ import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.system.staff.mapper.DmEmpAttendanceMapper; | |||
| import com.xueyi.system.staff.service.IDmEmpAttendanceService; | |||
| import com.xueyi.system.staff.service.impl.DmEmpAttendanceServiceImpl; | |||
| import org.apache.poi.ss.usermodel.FillPatternType; | |||
| import org.apache.poi.ss.usermodel.IndexedColors; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| 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.RestController; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| import java.io.Serializable; | |||
| import java.lang.annotation.Annotation; | |||
| import java.net.URLEncoder; | |||
| import java.text.ParseException; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Set; | |||
| /** | |||
| * 员工考勤管理 业务处理 | |||
| @@ -44,6 +67,9 @@ public class DmEmpAttendanceController extends BaseController<DmEmpAttendanceQue | |||
| @Autowired | |||
| private DmEmpAttendanceConverter converter; | |||
| @Autowired | |||
| private DmEmpAttendanceServiceImpl attendanceService; | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| protected String getNodeName() { | |||
| @@ -102,38 +128,102 @@ public class DmEmpAttendanceController extends BaseController<DmEmpAttendanceQue | |||
| @PostMapping("/export") | |||
| @RequiresPermissions(Auth.DM_EMP_ATTENDANCE_EXPORT) | |||
| @Log(title = "员工考勤管理", businessType = BusinessType.EXPORT) | |||
| public void export(HttpServletResponse response, DmEmpAttendanceQuery dmEmpAttendance) { | |||
| // super.export(response, dmEmpAttendance); | |||
| ExcelUtil<DmEmpAttendanceDto> util = new ExcelUtil<>(DmEmpAttendanceDto.class); | |||
| QueryWrapper<DmEmpAttendancePo> query = new QueryWrapper<DmEmpAttendancePo>(); | |||
| try { | |||
| public void export(HttpServletResponse response, DmEmpAttendanceQuery dmEmpAttendance) { | |||
| Class<?> yourClass = DmEmpAttendancePo.class; // 替换成你的类 | |||
| Class<? extends Annotation> annotationClass = ExcelProperty.class; // 替换成你的注解类 | |||
| Set<String> annotatedFields = ObjectUtil.findAnnotatedFields(yourClass, annotationClass); | |||
| response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); | |||
| response.setCharacterEncoding("utf-8"); | |||
| Date start = null; | |||
| Date end = null; | |||
| try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) { | |||
| QueryWrapper<DmEmpAttendancePo> query = new QueryWrapper<>(); | |||
| if (dmEmpAttendance != null && dmEmpAttendance.getETimestamp() != null &&dmEmpAttendance.getETimestamp()>0) { | |||
| String sTime = DateUtils.formatDate(DateUtils.parseLongToDate(dmEmpAttendance.getSTimestamp()),"yyyy-MM-dd"); | |||
| String eTime = DateUtils.formatDate(DateUtils.parseLongToDate(dmEmpAttendance.getETimestamp()),"yyyy-MM-dd"); | |||
| start = DateUtils.parseLongToDate(dmEmpAttendance.getSTimestamp()); | |||
| end = DateUtils.parseLongToDate(dmEmpAttendance.getETimestamp()); | |||
| String sTime = DateUtils.formatDate(start,"yyyy-MM-dd"); | |||
| String eTime = DateUtils.formatDate(end,"yyyy-MM-dd"); | |||
| query.between("date_str",sTime, eTime); | |||
| } else { | |||
| start = DateUtils.addDays(new Date(), -30); | |||
| end = new Date(); | |||
| } | |||
| if (dmEmpAttendance != null && dmEmpAttendance.getDeptId() !=null && dmEmpAttendance.getDeptId() > 0) { | |||
| query.eq("dept_id", dmEmpAttendance.getDeptId()); | |||
| } | |||
| if (dmEmpAttendance != null && dmEmpAttendance.getUserType() != null ) { | |||
| query.eq("user_type", dmEmpAttendance.getUserType()); | |||
| } | |||
| if (dmEmpAttendance != null && dmEmpAttendance.getUserName() != null ) { | |||
| query.like("user_name", dmEmpAttendance.getUserName()); | |||
| } | |||
| List<DmEmpAttendancePo> list = mapper.selectList(query); | |||
| List<DmEmpAttendanceDto> dtos = new ArrayList<>(list.size()); | |||
| list.forEach(item ->{ | |||
| DmEmpAttendanceDto dto = converter.mapperDto(item); | |||
| dto = dto.fixExcel(); | |||
| dtos.add(dto); | |||
| SysDeptPo deptPo = deptMapper.selectById(item.getDeptId()); | |||
| if (deptPo!=null) { | |||
| dto.setDeptName(deptPo.getName()); | |||
| List<List<String>> re = new ArrayList<>(); | |||
| if (list != null && list.size() > 0) { | |||
| re = attendanceService.groupAndTransform(list, start, end); | |||
| } | |||
| String fileName = URLEncoder.encode("考勤数据导出", "UTF-8").replaceAll("\\+", "%20"); | |||
| response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); | |||
| WriteFont contentWriteFont = new WriteFont(); | |||
| contentWriteFont.setFontHeightInPoints((short)16); | |||
| contentWriteFont.setBold(true); | |||
| WriteFont contentWriteFont2 = new WriteFont(); | |||
| contentWriteFont2.setFontHeightInPoints((short)12); | |||
| contentWriteFont2.setColor(IndexedColors.RED.getIndex()); | |||
| List heads = DmEmpAttendancePo.head(start, end); | |||
| WriteSheet writeSheet2 = EasyExcel.writerSheet(0, "考勤月度统计表").registerWriteHandler(new CellWriteHandler(){ | |||
| @Override | |||
| public void afterCellDispose(CellWriteHandlerContext context) { | |||
| if (BooleanUtils.isTrue(context.getHead())) { | |||
| WriteCellData<?> cellData = context.getFirstCellData(); | |||
| WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); | |||
| writeCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); | |||
| writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); | |||
| writeCellStyle.setShrinkToFit(true); | |||
| context.getRow().setHeight((short) (900)); | |||
| if (context.getRow().getRowNum()== 0 || context.getRow().getRowNum()== 1) { | |||
| writeCellStyle.setWriteFont(contentWriteFont); | |||
| } | |||
| context.getRow().getSheet().setColumnWidth(context.getColumnIndex(), 3000); | |||
| } else { | |||
| String str = context.getCell().getStringCellValue(); | |||
| if (str != null) { | |||
| context.getRow().setHeight((short) (450)); | |||
| } | |||
| if (str != null && (str.contains("迟到") || str.contains("早退")|| str.contains("缺勤"))) { | |||
| WriteCellData<?> cellData = context.getFirstCellData(); | |||
| WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); | |||
| writeCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); | |||
| writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); | |||
| writeCellStyle.setShrinkToFit(true); | |||
| writeCellStyle.setWriteFont(contentWriteFont2); | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| util.exportExcel(response, dtos, StrUtil.format("{}数据", getNodeName())); | |||
| }).head(heads).build(); | |||
| excelWriter.write(re, writeSheet2); | |||
| WriteSheet writeSheet = EasyExcel.writerSheet(1, "考勤流水记录表").head(DmEmpAttendancePo.class).includeColumnFieldNames(annotatedFields).build(); | |||
| excelWriter.write(list, writeSheet); | |||
| excelWriter.finish(); | |||
| } catch (IOException e) { | |||
| throw new RuntimeException(e); | |||
| } catch (ParseException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| package com.xueyi.system.staff.domain.converter; | |||
| import com.alibaba.excel.converters.Converter; | |||
| import com.alibaba.excel.enums.CellDataTypeEnum; | |||
| import com.alibaba.excel.metadata.GlobalConfiguration; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.metadata.property.ExcelContentProperty; | |||
| import com.xueyi.common.cache.utils.DictUtil; | |||
| import com.xueyi.system.api.dict.domain.dto.SysDictDataDto; | |||
| import java.util.List; | |||
| /** | |||
| * @author yk | |||
| * @description EasyExcel 用户类型转换 int 转 string | |||
| * @date 2023-12-27 15:31 | |||
| */ | |||
| public class DescTypeConverter implements Converter<Integer> { | |||
| @Override | |||
| public Class supportJavaTypeKey() { | |||
| return Integer.class; | |||
| } | |||
| @Override | |||
| public CellDataTypeEnum supportExcelTypeKey() { | |||
| return CellDataTypeEnum.STRING; | |||
| } | |||
| @Override | |||
| public WriteCellData<String> convertToExcelData(Integer integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { | |||
| List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_attendance_desc"); | |||
| String val = ""; | |||
| for (SysDictDataDto dictDataDto : dictDataDtos) { | |||
| if (dictDataDto.getValue().equals(integer.toString())) { | |||
| val = dictDataDto.getLabel(); | |||
| break; | |||
| } | |||
| } | |||
| return new WriteCellData<>(val); | |||
| } | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| package com.xueyi.system.staff.domain.converter; | |||
| import com.alibaba.excel.converters.Converter; | |||
| import com.alibaba.excel.enums.CellDataTypeEnum; | |||
| import com.alibaba.excel.metadata.GlobalConfiguration; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.metadata.property.ExcelContentProperty; | |||
| import com.xueyi.common.core.utils.core.NumberUtil; | |||
| /** | |||
| * @author yk | |||
| * @description EalExcel duration转换 | |||
| * @date 2023-12-27 15:31 | |||
| */ | |||
| public class DurationConverter implements Converter<Integer> { | |||
| @Override | |||
| public Class supportJavaTypeKey() { | |||
| return Integer.class; | |||
| } | |||
| @Override | |||
| public CellDataTypeEnum supportExcelTypeKey() { | |||
| return CellDataTypeEnum.STRING; | |||
| } | |||
| @Override | |||
| public WriteCellData<String> convertToExcelData(Integer integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { | |||
| return new WriteCellData<>(NumberUtil.convertMinutesToHoursMinutes(integer)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| package com.xueyi.system.staff.domain.converter; | |||
| import com.alibaba.excel.converters.Converter; | |||
| import com.alibaba.excel.enums.CellDataTypeEnum; | |||
| import com.alibaba.excel.metadata.GlobalConfiguration; | |||
| import com.alibaba.excel.metadata.data.WriteCellData; | |||
| import com.alibaba.excel.metadata.property.ExcelContentProperty; | |||
| import com.xueyi.common.cache.utils.DictUtil; | |||
| import com.xueyi.system.api.dict.domain.dto.SysDictDataDto; | |||
| import java.util.List; | |||
| /** | |||
| * @author yk | |||
| * @description EasyExcel 用户类型转换 int 转 string | |||
| * @date 2023-12-27 15:31 | |||
| */ | |||
| public class UserTypeConverter implements Converter<Long> { | |||
| @Override | |||
| public Class supportJavaTypeKey() { | |||
| return Integer.class; | |||
| } | |||
| @Override | |||
| public CellDataTypeEnum supportExcelTypeKey() { | |||
| return CellDataTypeEnum.STRING; | |||
| } | |||
| @Override | |||
| public WriteCellData<String> convertToExcelData(Long integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { | |||
| List<SysDictDataDto> dictDataDtos = DictUtil.getDictCache("dm_emp_type"); | |||
| String val = ""; | |||
| for (SysDictDataDto dictDataDto : dictDataDtos) { | |||
| if (dictDataDto.getValue().equals(integer.toString())) { | |||
| val = dictDataDto.getLabel(); | |||
| break; | |||
| } | |||
| } | |||
| return new WriteCellData<>(val); | |||
| } | |||
| } | |||
| @@ -1,13 +1,25 @@ | |||
| package com.xueyi.system.staff.domain.po; | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.annotation.format.DateTimeFormat; | |||
| import com.alibaba.excel.annotation.write.style.ColumnWidth; | |||
| import com.alibaba.excel.annotation.write.style.ContentRowHeight; | |||
| import com.alibaba.excel.annotation.write.style.HeadRowHeight; | |||
| import com.alibaba.excel.annotation.write.style.HeadStyle; | |||
| import com.alibaba.excel.enums.poi.FillPatternTypeEnum; | |||
| import com.alibaba.excel.util.ListUtils; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import com.xueyi.common.core.annotation.Excel; | |||
| import com.xueyi.common.core.web.tenant.base.TBaseEntity; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.staff.domain.converter.DurationConverter; | |||
| import com.xueyi.system.staff.domain.converter.UserTypeConverter; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import java.io.Serial; | |||
| import java.util.Arrays; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import static com.xueyi.common.core.constant.basic.EntityConstants.NAME; | |||
| import static com.xueyi.common.core.constant.basic.EntityConstants.REMARK; | |||
| @@ -22,39 +34,72 @@ import static com.xueyi.common.core.constant.basic.EntityConstants.STATUS; | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| @TableName(value = "dm_emp_attendance", excludeProperty = { STATUS, SORT, REMARK, NAME }) | |||
| @HeadRowHeight(40) | |||
| @ContentRowHeight(20) | |||
| @ColumnWidth(20) | |||
| @HeadStyle(fillForegroundColor = 34, fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND) | |||
| public class DmEmpAttendancePo extends TBaseEntity { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| @ExcelProperty("日期") | |||
| @ColumnWidth(25) | |||
| private String dateStr; | |||
| /** 人员名 */ | |||
| @Excel(name = "人员名", sort = 3) | |||
| @ExcelProperty("人员名") | |||
| protected String userName; | |||
| /** 人员ID */ | |||
| @Excel(name = "人员ID", sort = 2) | |||
| protected Long userId; | |||
| /** 人员类型 */ | |||
| @Excel(name = "人员类型", readConverterExp = "5=员工,4=高管", sort = 4) | |||
| @ExcelProperty(value = "人员类型", converter = UserTypeConverter.class) | |||
| protected Long userType; | |||
| /** 当日最早打卡记录 */ | |||
| @DateTimeFormat("HH:mm") | |||
| @ExcelProperty("上班打卡") | |||
| protected Date checkInTime; | |||
| /** 当日最晚打卡记录 */ | |||
| @DateTimeFormat("HH:mm") | |||
| @ExcelProperty("下班打卡") | |||
| protected Date checkOutTime; | |||
| /** 工作时长(分钟) */ | |||
| @Excel(name = "工作时长", readConverterExp = "分=钟", sort = 8) | |||
| @ExcelProperty(value = "工作时长", converter = DurationConverter.class) | |||
| protected Integer workDuration; | |||
| /** 所属组织ID */ | |||
| protected Long deptId; | |||
| @Excel(name = "日期", sort = 1) | |||
| private String dateStr; | |||
| // @ExcelProperty(value = "考勤状态", converter = DescTypeConverter.class) | |||
| protected Integer descStatus; | |||
| public static List<List<String>> head(Date startDate, Date endDate) { | |||
| List<String> base = Arrays.asList("考勤记录", DateUtils.formatDate(startDate,"yyyy年MM月dd日")+" 到 "+DateUtils.formatDate(endDate,"yyyy年MM月dd日")); | |||
| List<List<String>> head = ListUtils.newArrayList(); | |||
| List<String> _headRow = ListUtils.newArrayList(base); | |||
| _headRow.add(DateUtils.formatDate(startDate, "姓名")); | |||
| head.add(_headRow); | |||
| //从startDate到endDate开始循环 | |||
| while (startDate.compareTo(endDate) <= 0) { | |||
| List<String> headRow = ListUtils.newArrayList(base); | |||
| headRow.add(DateUtils.formatDate(startDate, "MM月dd日")); | |||
| List<String> headRow2 = ListUtils.newArrayList(headRow); | |||
| headRow2.add(DateUtils.getChineseWeek(startDate)); | |||
| head.add(headRow2); | |||
| startDate = DateUtils.addDays(startDate, 1); | |||
| } | |||
| return head; | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| package com.xueyi.system.staff.graphql; | |||
| import org.springframework.stereotype.Service; | |||
| /** | |||
| * @author yk | |||
| * @description | |||
| * @date 2023-12-25 19:55 | |||
| */ | |||
| @Service | |||
| public class VisitorGraphQLQuery { | |||
| } | |||
| @@ -4,10 +4,14 @@ import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.common.web.entity.manager.IBaseManager; | |||
| import java.util.List; | |||
| /** | |||
| * 员工考勤管理 数据封装层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmEmpAttendanceManager extends IBaseManager<DmEmpAttendanceQuery, DmEmpAttendanceDto> { | |||
| @Override | |||
| List<DmEmpAttendanceDto> selectList(DmEmpAttendanceQuery query); | |||
| } | |||
| @@ -1,6 +1,10 @@ | |||
| package com.xueyi.system.staff.manager.impl; | |||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
| import com.xueyi.common.core.utils.core.ObjectUtil; | |||
| import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.model.DmEmpAttendanceConverter; | |||
| import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| @@ -9,6 +13,9 @@ import com.xueyi.system.staff.manager.IDmEmpAttendanceManager; | |||
| import com.xueyi.system.staff.mapper.DmEmpAttendanceMapper; | |||
| import org.springframework.stereotype.Component; | |||
| import java.text.ParseException; | |||
| import java.util.List; | |||
| /** | |||
| * 员工考勤管理 数据封装层处理 | |||
| * | |||
| @@ -16,4 +23,35 @@ import org.springframework.stereotype.Component; | |||
| */ | |||
| @Component | |||
| public class DmEmpAttendanceManager extends BaseManagerImpl<DmEmpAttendanceQuery, DmEmpAttendanceDto, DmEmpAttendancePo, DmEmpAttendanceMapper, DmEmpAttendanceConverter> implements IDmEmpAttendanceManager { | |||
| @Override | |||
| public List<DmEmpAttendanceDto> selectList(DmEmpAttendanceQuery query) { | |||
| return super.selectList(query); | |||
| } | |||
| @Override | |||
| protected LambdaQueryWrapper<DmEmpAttendancePo> selectListQuery(DmEmpAttendanceQuery query) { | |||
| return Wrappers.<DmEmpAttendancePo>query(query).lambda() | |||
| .func(i -> { | |||
| if (ObjectUtil.isNotNull(query.getETimestamp()) && ObjectUtil.isNotNull(query.getSTimestamp())){ | |||
| // 日期范围查询,时间戳转yyyy-MM-dd格式 | |||
| try { | |||
| String endTime = DateUtils.praseLongToDateString(query.getETimestamp()); | |||
| String startTime = DateUtils.praseLongToDateString(query.getSTimestamp()); | |||
| endTime = (endTime != null ? endTime.substring(0,10):""); | |||
| startTime = (startTime != null ? startTime.substring(0,10):""); | |||
| i.apply("date_str between '{0}' and '{1}'", startTime, endTime); | |||
| } catch (ParseException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| }) | |||
| .func(i -> { | |||
| if (ObjectUtil.isNotNull(query.getUserName())) { | |||
| i.apply("user_name like '%{0}%'", query.getUserName()); | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -1,9 +1,13 @@ | |||
| package com.xueyi.system.staff.service; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.common.web.entity.service.IBaseService; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| /** | |||
| * 员工考勤管理 服务层 | |||
| @@ -14,4 +18,7 @@ public interface IDmEmpAttendanceService extends IBaseService<DmEmpAttendanceQue | |||
| @TenantIgnore(tenantLine = true) | |||
| public Integer selectCountIgnoreTenant(); | |||
| public List<List<String>> groupAndTransform(List<DmEmpAttendancePo> list, Date start, Date end); | |||
| } | |||
| @@ -1,19 +1,31 @@ | |||
| package com.xueyi.system.staff.service.impl; | |||
| import cn.hutool.core.date.LocalDateTimeUtil; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.xueyi.common.cache.utils.DictUtil; | |||
| import com.xueyi.common.core.utils.DateUtil; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.system.api.dict.domain.dto.SysDictDataDto; | |||
| import com.xueyi.system.staff.domain.dto.DmEmpAttendanceDto; | |||
| import com.xueyi.system.staff.domain.po.DmEmpAttendancePo; | |||
| import com.xueyi.system.staff.domain.query.DmEmpAttendanceQuery; | |||
| import com.xueyi.system.staff.manager.IDmEmpAttendanceManager; | |||
| import com.xueyi.system.staff.mapper.DmEmpAttendanceMapper; | |||
| import com.xueyi.system.staff.service.IDmEmpAttendanceService; | |||
| import com.xueyi.system.staff.manager.IDmEmpAttendanceManager; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.Serializable; | |||
| import java.time.LocalDate; | |||
| import java.time.ZoneId; | |||
| import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| /** | |||
| * 员工考勤管理 服务层处理 | |||
| @@ -54,6 +66,38 @@ public class DmEmpAttendanceServiceImpl extends BaseServiceImpl<DmEmpAttendanceQ | |||
| } | |||
| } | |||
| @Override | |||
| public List<List<String>> groupAndTransform(List<DmEmpAttendancePo> list, Date start, Date end) { | |||
| Map<String, Map<LocalDate, List<DmEmpAttendancePo>>> grouped = list.stream() | |||
| .collect(Collectors.groupingBy(DmEmpAttendancePo::getUserName, | |||
| Collectors.groupingBy(a -> LocalDate.ofInstant(DateUtil.parseDate(a.getDateStr()).toInstant(), ZoneId.systemDefault())))); | |||
| // Find start and end dates | |||
| LocalDate startDate = LocalDateTimeUtil.of(start).toLocalDate(); | |||
| LocalDate endDate = LocalDateTimeUtil.of(end).toLocalDate(); | |||
| 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()); | |||
| return grouped.entrySet().stream() | |||
| .map(entry -> { | |||
| List<String> row = new ArrayList<>(); | |||
| row.add(entry.getKey()); // Add name | |||
| for (LocalDate date : dateRange) { | |||
| List<DmEmpAttendancePo> dateList = entry.getValue().getOrDefault(date, Collections.emptyList()); | |||
| String status = dateList.isEmpty() ? "" : dictMap.get(dateList.get(0).getDescStatus().toString()); | |||
| row.add(status); | |||
| } | |||
| return row; | |||
| }) | |||
| .collect(Collectors.toList()); | |||
| } | |||
| public void updRedisCount(){ | |||
| if (redisTemplate.hasKey("dashboard:attendance")) { | |||
| redisTemplate.opsForValue().increment("dashboard:attendance"); | |||
| @@ -5,21 +5,30 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| 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; | |||
| import com.xueyi.system.staff.domain.query.DmStaffQuery; | |||
| import com.xueyi.system.staff.manager.IDmStaffManager; | |||
| import com.xueyi.system.staff.mapper.DmEmpAttendanceMapper; | |||
| import com.xueyi.system.staff.mapper.DmStaffMapper; | |||
| import com.xueyi.system.staff.service.IDmStaffService; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.PostConstruct; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| * 人员管理 服务层处理 | |||
| @@ -29,12 +38,35 @@ import java.util.List; | |||
| @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; | |||
| @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; | |||
| @Autowired | |||
| DmEmpAttendanceMapper dmEmpAttendanceMapper; | |||
| @Autowired | |||
| SysDeptExtMapper sysDeptExtMapper; | |||
| @Autowired | |||
| private DmEmpAttendanceServiceImpl dmEmpAttendanceService; | |||
| /** | |||
| @@ -106,6 +138,9 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto | |||
| } | |||
| DmEmpAttendancePo empAttendance = dmEmpAttendanceMapper.findByEmpAndDate(checkTimeDateStr, userId); | |||
| SysDeptExt ext = sysDeptExtMapper.selectWorkTimeByDeptId(emp.getDeptId()); | |||
| logger.info("deptId:{}", emp.getDeptId()); | |||
| logger.info("ext:start-end:{} end-start:{}" ,ext.getOnDutyHourEnd(), ext.getOffDutyHourStart()); | |||
| if (null != empAttendance) { | |||
| @@ -115,12 +150,27 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto | |||
| empAttendance.setCheckOutTime(checkTime); | |||
| } | |||
| if (null!=empAttendance.getCheckInTime() && null != empAttendance.getCheckOutTime()) { | |||
| Date cin = empAttendance.getCheckInTime(); | |||
| Date cout = empAttendance.getCheckOutTime(); | |||
| Integer diffMin = DateUtils.dateDiffMin(cin, cout); | |||
| empAttendance.setWorkDuration(diffMin); | |||
| } | |||
| if (DateUtils.formatDate(checkTime, "HH:mm").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")); | |||
| } | |||
| } 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")); | |||
| } | |||
| } | |||
| QueryWrapper<DmEmpAttendancePo> wrapper = new QueryWrapper<>(); | |||
| wrapper.eq("id",empAttendance.getId()); | |||
| dmEmpAttendanceMapper.update(empAttendance, wrapper); | |||
| @@ -129,6 +179,17 @@ public class DmStaffServiceImpl extends BaseServiceImpl<DmStaffQuery, DmStaffDto | |||
| DmEmpAttendancePo ea = new DmEmpAttendancePo(); | |||
| Date checkDate = DateUtils.parseStrToDate(DateUtils.formatDate(checkTime, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss"); | |||
| ea.setCheckInTime(checkDate); | |||
| DmHolidayPo holidayPo = holidayService.isHoliday(checkDate); | |||
| if (DateUtils.formatDate(checkDate, "HH:mm").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")); | |||
| } | |||
| } | |||
| ea.setDateStr(DateUtils.formatDate(new Date(), "yyyy-MM-dd")); | |||
| ea.setUserId(userId); | |||
| @@ -0,0 +1,13 @@ | |||
| schema { | |||
| query: Query | |||
| mutation: Mutation | |||
| } | |||
| type Query{ | |||
| } | |||
| type Mutation{ | |||
| } | |||
| @@ -0,0 +1,4 @@ | |||
| type R{ | |||
| code: Int! | |||
| msg: String | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| extend type Query{ | |||
| getVisitorList() | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package com.xueyi.tenant.tenant.controller; | |||
| import cn.hutool.core.text.CharSequenceUtil; | |||
| import com.xueyi.common.core.constant.basic.BaseConstants; | |||
| import com.xueyi.common.core.constant.system.OrganizeConstants; | |||
| import com.xueyi.common.core.utils.core.CollUtil; | |||
| @@ -16,12 +17,24 @@ import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.security.auth.Auth; | |||
| import com.xueyi.common.web.entity.controller.BaseController; | |||
| import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| 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.SysStaffMapper; | |||
| import com.xueyi.tenant.tenant.mapper.TeTenantMapper; | |||
| import com.xueyi.tenant.tenant.service.ITeTenantService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| 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 javax.servlet.http.HttpServletResponse; | |||
| import java.io.Serializable; | |||
| @@ -42,6 +55,12 @@ public class TeTenantController extends BaseController<TeTenantQuery, TeTenantDt | |||
| return "租户"; | |||
| } | |||
| @Autowired | |||
| private TeTenantMapper teTenantMapper; | |||
| @Autowired | |||
| private SysStaffMapper staffMapper; | |||
| /** | |||
| * 租户新增 | 内部调用 | |||
| */ | |||
| @@ -57,6 +76,21 @@ public class TeTenantController extends BaseController<TeTenantQuery, TeTenantDt | |||
| R<List<TeTenantDto>> tenantList() { | |||
| return R.ok(super.baseService.selectList(new TeTenantQuery())); | |||
| } | |||
| @InnerAuth | |||
| @GetMapping("/one") | |||
| R<TeTenantPo> tenant(@RequestParam("phone") String phone) { | |||
| TeTenantPo po = teTenantMapper.selectByPhone(phone); | |||
| return R.ok(po); | |||
| } | |||
| @InnerAuth | |||
| @GetMapping("/staff") | |||
| R<SysStaffPo> staff(@RequestParam("phone") String phone) { | |||
| SysStaffPo po = staffMapper.selectByPhone(phone); | |||
| return R.ok(po); | |||
| } | |||
| /** | |||
| * 查询租户列表 | |||
| */ | |||
| @@ -170,10 +204,10 @@ public class TeTenantController extends BaseController<TeTenantQuery, TeTenantDt | |||
| if (baseService.checkIsDefault(idList.get(i))) | |||
| idList.remove(i); | |||
| if (CollUtil.isEmpty(idList)) { | |||
| warn(StrUtil.format("删除失败,默认{}不允许删除!", getNodeName())); | |||
| warn(CharSequenceUtil.format("删除失败,默认{}不允许删除!", getNodeName())); | |||
| } else if (idList.size() != size) { | |||
| baseService.deleteByIds(idList); | |||
| warn(StrUtil.format("默认{}不允许删除,其余{}删除成功!", getNodeName(), getNodeName())); | |||
| warn(CharSequenceUtil.format("默认{}不允许删除,其余{}删除成功!", getNodeName(), getNodeName())); | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| package com.xueyi.tenant.tenant.mapper; | |||
| import com.xueyi.common.datasource.annotation.Master; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.mapper.BaseMapper; | |||
| import com.xueyi.tenant.api.tenant.domain.dto.SysStaffDto; | |||
| import com.xueyi.tenant.api.tenant.domain.po.SysStaffPo; | |||
| import com.xueyi.tenant.api.tenant.domain.query.SysStaffQuery; | |||
| import org.apache.ibatis.annotations.Param; | |||
| /** | |||
| * 租户管理 数据层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Master | |||
| public interface SysStaffMapper extends BaseMapper<SysStaffQuery, SysStaffDto, SysStaffPo> { | |||
| @TenantIgnore(tenantLine = true) | |||
| SysStaffPo selectByPhone(@Param("phone") String phone); | |||
| } | |||
| @@ -1,10 +1,12 @@ | |||
| package com.xueyi.tenant.tenant.mapper; | |||
| import com.xueyi.common.datasource.annotation.Master; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.mapper.BaseMapper; | |||
| import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto; | |||
| import com.xueyi.tenant.api.tenant.domain.po.TeTenantPo; | |||
| import com.xueyi.tenant.api.tenant.domain.query.TeTenantQuery; | |||
| import org.apache.ibatis.annotations.Param; | |||
| /** | |||
| * 租户管理 数据层 | |||
| @@ -13,4 +15,6 @@ import com.xueyi.tenant.api.tenant.domain.query.TeTenantQuery; | |||
| */ | |||
| @Master | |||
| public interface TeTenantMapper extends BaseMapper<TeTenantQuery, TeTenantDto, TeTenantPo> { | |||
| @TenantIgnore(tenantLine = true) | |||
| TeTenantPo selectByPhone(@Param("phone") String phone); | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <!DOCTYPE mapper | |||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
| <mapper namespace="com.xueyi.tenant.tenant.mapper.SysStaffMapper"> | |||
| <select id="selectByPhone" resultType="com.xueyi.tenant.api.tenant.domain.po.SysStaffPo"> | |||
| select tenant_id from dm_staff where phone = #{phone} and del_flag = 0 limit 1 | |||
| </select> | |||
| </mapper> | |||
| @@ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <!DOCTYPE mapper | |||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
| <mapper namespace="com.xueyi.tenant.tenant.mapper.TeTenantMapper"> | |||
| <select id="selectByPhone" resultType="com.xueyi.tenant.api.tenant.domain.po.TeTenantPo" parameterType="Object"> | |||
| select * from te_tenant where id = (select tenant_id from dm_staff where phone = #{phone} and del_flag = 0 limit 1) | |||
| </select> | |||
| </mapper> | |||