commit
60bef14d39
@ -0,0 +1,52 @@ |
||||
package com.zilber.boot.dahua.accesscontrol; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class QueryRecordRequest { |
||||
|
||||
/** 页码,正整数 */ |
||||
private Integer pageNum; |
||||
/** 分页大小,正整数 */ |
||||
private Integer pageSize; |
||||
/** 查询开始时间,格式:yyyy-MM-dd HH:mm:ss */ |
||||
private String startSwingTime; |
||||
/** 查询结束时间,格式:yyyy-MM-dd HH:mm:ss */ |
||||
private String endSwingTime; |
||||
/** 入库开始时间,格式:yyyy-MM-dd HH:mm:ss */ |
||||
private String startCreateTime; |
||||
/** 入库结束时间,格式:yyyy-MM-dd HH:mm:ss */ |
||||
private String endCreateTime; |
||||
/** 开门类型 */ |
||||
private Integer openType; |
||||
/** 开门类型多选 */ |
||||
private List<Integer> openTypes; |
||||
/** 卡片类型 */ |
||||
private String category; |
||||
/** 人员名称 */ |
||||
private String personName; |
||||
/** 人员编号 */ |
||||
private String personCode; |
||||
/** 通道编码列表 */ |
||||
private List<String> channelCodes; |
||||
/** 部门ID */ |
||||
private String deptIds; |
||||
/** 卡号 */ |
||||
private String cardNumber; |
||||
/** 事件类型 */ |
||||
private Integer enterOrExit; |
||||
/** 开门结果 */ |
||||
private Integer openResult; |
||||
/** 是否超温 */ |
||||
private Boolean overTemp; |
||||
/** 体温低限 */ |
||||
private Float curTempStart; |
||||
/** 体温高限 */ |
||||
private Float curTempEnd; |
||||
/** 口罩状态 3-带口罩,2—没带口罩,1-未识别 */ |
||||
private Integer maskState; |
||||
/** 访客筛选,1 - 只查询访客记录 2 - 只查询非访客记录 */ |
||||
private Integer visitorFilter; |
||||
} |
@ -0,0 +1,84 @@ |
||||
package com.zilber.boot.dahua.accesscontrol; |
||||
|
||||
import com.dahuatech.icc.oauth.http.IccResponse; |
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class QueryRecordResponse extends IccResponse { |
||||
|
||||
/** */ |
||||
private Data data; |
||||
|
||||
@lombok.Data |
||||
public static class Data { |
||||
/** 当前页 */ |
||||
private Integer currentPage; |
||||
/** 是否启用云数据库,false-不启用,true-启用 */ |
||||
private Boolean enableCloudDB; |
||||
/** 分页大小 */ |
||||
private Integer pageSize; |
||||
/** 总页码 */ |
||||
private Integer totalPage; |
||||
/** 总条数 */ |
||||
private Integer totalRows; |
||||
/** 分页数据 */ |
||||
private List<PageData> pageData; |
||||
|
||||
@lombok.Data |
||||
public static class PageData{ |
||||
/** 卡号 */ |
||||
private String cardNumber; |
||||
/** 卡状态,-1-空白卡,0-正常卡,1-挂失卡,2-注销卡 */ |
||||
private Integer cardStatus; |
||||
/** 卡类型,0-IC卡, 1-有源RFID, 2-CPU卡 */ |
||||
private Integer cardType; |
||||
/** 通道编码 */ |
||||
private String channelCode; |
||||
/** 通道名称 */ |
||||
private String channelName; |
||||
/** 部门名称 */ |
||||
private String deptName; |
||||
/** 设备编码 */ |
||||
private String deviceCode; |
||||
/** 设备名称 */ |
||||
private String deviceName; |
||||
/** 进出门类型,1-进门, 2出门, 3-进/出门 */ |
||||
private Integer enterOrExit; |
||||
/** 记录id */ |
||||
private Long id; |
||||
/** 1-内部人员, 2-访客 */ |
||||
private Integer imageType; |
||||
/** 开门结果,0-失败,1-成功 */ |
||||
private Integer openResult; |
||||
/** 开门类型 */ |
||||
private Integer openType; |
||||
/** 证件号码 */ |
||||
private String paperNumber; |
||||
/** 人员编号 */ |
||||
private String personCode; |
||||
/** 人员ID */ |
||||
private Long personId; |
||||
/** 人员姓名 */ |
||||
private String personName; |
||||
/** 抓图,相对路径 */ |
||||
private String recordImageUrl; |
||||
/** 抓图,绝对路径 */ |
||||
private String recordImage; |
||||
/** 开门失败原因 */ |
||||
private String remark; |
||||
/** 刷卡时间 */ |
||||
private String swingTime; |
||||
/** 入库时间 */ |
||||
private String createTime; |
||||
/** 口罩状态(3-带口罩,2—没带口罩,1-未识别) */ |
||||
private Integer maskState; |
||||
/** 是否超温 */ |
||||
private Boolean overTemp; |
||||
/** 体温 */ |
||||
private Float curTemp; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,37 @@ |
||||
package com.zilber.boot.dahua.attendance; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* program:java-sdk-demo |
||||
* @Author: 355079 |
||||
* @Date:2024-04-28 14:06 |
||||
* @Description: 打卡记录查询请求参数 |
||||
*/ |
||||
@Data |
||||
public class GetRecordPageRequest { |
||||
/** 当前页 */ |
||||
private Integer pageNum; |
||||
/** 每页记录数 */ |
||||
private Integer pageSize; |
||||
/** 开始时间,格式: yyyy-MM-dd HH:mm:ss */ |
||||
private String actionTimeAfter; |
||||
/** 结束时间,格式: yyyy-MM-dd HH:mm:ss */ |
||||
private String actionTimeBefore; |
||||
/** 卡号 */ |
||||
private String cardNo; |
||||
/** 考勤类型(0:刷卡考勤;1:人像考勤;2:指纹考勤) */ |
||||
private String attendanceType; |
||||
/** 人员id集合 */ |
||||
private List<Long> personIds; |
||||
/** 模糊查询参数(人员姓名) */ |
||||
private String personName; |
||||
/** 模糊查询参数(人员编号) */ |
||||
private String personCode; |
||||
/** 排序字段 */ |
||||
private String sort; |
||||
/** DESC-降序, ASC-升序 */ |
||||
private String sortType; |
||||
} |
@ -0,0 +1,53 @@ |
||||
package com.zilber.boot.dahua.attendance; |
||||
|
||||
import com.dahuatech.icc.oauth.http.IccResponse; |
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* program:java-sdk-demo |
||||
* @Author: 355079 |
||||
* @Date:2024-04-28 14:13 |
||||
* @Description: 打卡记录查询返回参数 |
||||
*/ |
||||
@Data |
||||
public class GetRecordPageResponse extends IccResponse { |
||||
private Data data; |
||||
@lombok.Data |
||||
public static class Data{ |
||||
/** 当前页 */ |
||||
private Integer currentPage; |
||||
/** 每页条数 */ |
||||
private Integer pageSize; |
||||
/** 总页数 */ |
||||
private Integer totalPage; |
||||
/** 总条数 */ |
||||
private Integer totalRows; |
||||
/** 分页数据 */ |
||||
private List<PageData> pageData; |
||||
@lombok.Data |
||||
public static class PageData{ |
||||
/** 刷卡时间(yyyy-MM-dd HH:mm:ss) */ |
||||
private String actionTime; |
||||
/** 考勤方式 */ |
||||
private String attendanceType; |
||||
/** 卡号 */ |
||||
private String cardNo; |
||||
/** 部门名称 */ |
||||
private String deptName; |
||||
/** 人员编号 */ |
||||
private String personCode; |
||||
/** 人员id */ |
||||
private Integer personId; |
||||
/** 人员姓名 */ |
||||
private String personName; |
||||
/** 上报时间(yyyy-MM-dd HH:mm:ss) */ |
||||
private String reportTime; |
||||
/** 考勤点id */ |
||||
private String siteId; |
||||
/** 考勤点名称 */ |
||||
private String siteName; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
package com.zilber.boot.dahua.attendance; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* program:java-sdk-demo |
||||
* |
||||
* @Author: 355079 |
||||
* @Date:2024-04-29 13:48 |
||||
* @Description: 分页获取考勤结果请求参数 |
||||
*/ |
||||
@Data |
||||
public class GetResultPageRequest { |
||||
/** 第几页 */ |
||||
private Integer pageNum; |
||||
/** 每页条数 */ |
||||
private Integer pageSize; |
||||
/** 开始时间(yyyy-MM-dd) */ |
||||
private String dutyDateAfter; |
||||
/** 结束时间(yyyy-MM-dd) */ |
||||
private String dutyDateBefore; |
||||
/** 考勤结果(0-异常,1-正常) */ |
||||
private Integer result; |
||||
/** 班次类型: 1-固定班, 2-弹性班, 3-签到班, 4-休班 */ |
||||
private String dailyType; |
||||
/** 单个人员编号 */ |
||||
private String personCode; |
||||
/** 部门id(部门间以逗号隔开) */ |
||||
private String deptIdsString; |
||||
/** 人员id集合 */ |
||||
private List<Long> personIds; |
||||
/** 班次中各时段状态: 0-异常, 1-正常 */ |
||||
private List<Integer> attendanceStatus; |
||||
/** 选择的班次id集合 */ |
||||
private List<Long> classesIds; |
||||
/** 排序字段 */ |
||||
private String sort; |
||||
/** DESC-降序, ASC-升序 */ |
||||
private String sortType; |
||||
} |
@ -0,0 +1,101 @@ |
||||
package com.zilber.boot.dahua.attendance; |
||||
|
||||
import com.dahuatech.icc.oauth.http.IccResponse; |
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* program:java-sdk-demo |
||||
* |
||||
* @Author: 355079 |
||||
* @Date:2024-04-29 14:21 |
||||
* @Description: 分页获取考勤结果请求参数 |
||||
*/ |
||||
@Data |
||||
public class GetResultPageResponse extends IccResponse { |
||||
private Data data; |
||||
@lombok.Data |
||||
public static class Data{ |
||||
/** 当前页 */ |
||||
private Integer currentPage; |
||||
/** 每页条数 */ |
||||
private Integer pageSize; |
||||
/** 总页数 */ |
||||
private Integer totalPage; |
||||
/** 总条数 */ |
||||
private Integer totalRows; |
||||
/** 分页数据 */ |
||||
private List<PageData> pageData; |
||||
@lombok.Data |
||||
public static class PageData{ |
||||
/** 考勤时间(yyyy-MM-dd) */ |
||||
private String dutyDate; |
||||
/** 员工姓名 */ |
||||
private String personName; |
||||
/** 员工编号 */ |
||||
private String personCode; |
||||
/** 员工id */ |
||||
private Long personId; |
||||
/** 部门id */ |
||||
private Integer departmentId; |
||||
/** 部门名称 */ |
||||
private String deptName; |
||||
/** 班次id */ |
||||
private String dailyId; |
||||
/** 班次名称 */ |
||||
private String dailyName; |
||||
/** 班次类型 */ |
||||
private Integer dailyType; |
||||
/** 考勤结果 */ |
||||
private Integer result; |
||||
/** 时间段1签入情况:0-异常,1-正常 */ |
||||
private Integer timeOneSignIn; |
||||
/** 时间段1签出情况 */ |
||||
private Integer timeOneSignOut; |
||||
/** 时间段2签入情况 */ |
||||
private Integer timeTwoSignIn; |
||||
/** 时间段2签出情况 */ |
||||
private Integer timeTwoSignOut; |
||||
/** 时间段3签入情况 */ |
||||
private Integer timeThreeSignIn; |
||||
/** 时间段3签出情况 */ |
||||
private Integer timeThreeSignOut; |
||||
/** 时间段4签入情况 */ |
||||
private Integer timeFourSignIn; |
||||
/** 时间段4签出情况 */ |
||||
private Integer timeFourSignOut; |
||||
/** 时间段5签入情况 */ |
||||
private Integer timeFiveSignIn; |
||||
/** 时间段5签出情况 */ |
||||
private Integer timeFiveSignOut; |
||||
/** 应勤时长,单位小时 */ |
||||
private Float plannedWorkHours; |
||||
/** 实际时长,单位小时 */ |
||||
private Float actualWorkHours; |
||||
/** 缺勤时长,单位小时 */ |
||||
private Float absenceWorkHours; |
||||
/** 旷工时长,单位小时 */ |
||||
private Float absenteeismWorkHours; |
||||
/** 迟到时长,单位小时 */ |
||||
private Float lateWorkHours; |
||||
/** 早退时长,单位小时 */ |
||||
private Float earlyLeaveWorkHours; |
||||
/** 出差时长,单位小时 */ |
||||
private Float travelWorkHours; |
||||
/** 周内加班时长 ,单位小时 */ |
||||
private Float overtimeWeekday; |
||||
/** 周末加班时长,单位小时 */ |
||||
private Float overtimeWeekend; |
||||
/** 节假日加班时长,单位小时 */ |
||||
private Float overtimeHoliday; |
||||
/** 无薪时长,单位小时 */ |
||||
private Float unpaidWorkHours; |
||||
/** 有薪时长,单位小时 */ |
||||
private Float paidWorkHours; |
||||
/** 单据编号 */ |
||||
private String documentNumber; |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
package com.zilber.boot.dahua.config; |
||||
|
||||
import com.dahuatech.icc.oauth.model.v202010.OauthConfigUserPwdInfo; |
||||
|
||||
/** |
||||
* 公钥加密 |
||||
* 使用RSA加密 |
||||
*/ |
||||
public class OauthConfigUtil { |
||||
/** |
||||
* 获取Oauth配置信息 |
||||
* |
||||
* @return Oauth配置信息 |
||||
*/ |
||||
public static OauthConfigUserPwdInfo getOauthConfig() { |
||||
PlatformConfig platformConfig = new PlatformConfig();//读取配置
|
||||
OauthConfigUserPwdInfo oauthConfigUserPwdInfo = new OauthConfigUserPwdInfo( |
||||
platformConfig.getHost(), |
||||
platformConfig.getClientId(), |
||||
platformConfig.getClientSecret(), |
||||
platformConfig.getUsername(), |
||||
platformConfig.getPassword(), |
||||
false, |
||||
platformConfig.getHttpsPort(), |
||||
platformConfig.getHttpPort() |
||||
); |
||||
oauthConfigUserPwdInfo.getHttpConfigInfo().setReadTimeout(platformConfig.getReadTimeout()); |
||||
oauthConfigUserPwdInfo.getHttpConfigInfo().setConnectionTimeout(platformConfig.getConnectionTimeout()); |
||||
return oauthConfigUserPwdInfo; |
||||
} |
||||
} |
@ -0,0 +1,89 @@ |
||||
package com.zilber.boot.dahua.config; |
||||
|
||||
/** |
||||
* 平台信息配置 |
||||
*/ |
||||
public class PlatformConfig { |
||||
|
||||
private String clientId = "CompanyName";//凭证ID自定义,配合申请凭证流程申请
|
||||
private String clientSecret = "42bec152-8f04-476a-9aec-e7d616ff3cb3";//凭证密钥,参考此地址申请https://open-icc.dahuatech.com/iccdoc/enterprisebase/5.0.15/wiki/common/quickstart.html#%E7%94%B3%E8%AF%B7OpenAPI%E7%94%A8%E6%88%B7
|
||||
private String username = "TEST";//平台登录用户名
|
||||
private String password = "OGR28u6_cc";//平台登录密码
|
||||
private String host = "124.160.33.135";//平台IP,联调环境IP
|
||||
private String httpsPort = "4077";//https默认端口是443,联调环境443映射外网端口为4077
|
||||
private String httpPort = "4078";//http默认端口是83,但不开启,,联调环境83映射外网端口为4078;需运维中心开启http调试模式后才支持;isEnableHttpTest=true时有效,
|
||||
private Long connectionTimeout = -1l;//连接超时
|
||||
private Long readTimeout = -1l;//读取超时
|
||||
|
||||
public String getClientId() { |
||||
return clientId; |
||||
} |
||||
|
||||
public void setClientId(String clientId) { |
||||
this.clientId = clientId; |
||||
} |
||||
|
||||
public String getClientSecret() { |
||||
return clientSecret; |
||||
} |
||||
|
||||
public void setClientSecret(String clientSecret) { |
||||
this.clientSecret = clientSecret; |
||||
} |
||||
|
||||
public String getUsername() { |
||||
return username; |
||||
} |
||||
|
||||
public void setUsername(String username) { |
||||
this.username = username; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
|
||||
public String getHost() { |
||||
return host; |
||||
} |
||||
|
||||
public void setHost(String host) { |
||||
this.host = host; |
||||
} |
||||
|
||||
public String getHttpsPort() { |
||||
return httpsPort; |
||||
} |
||||
|
||||
public void setHttpsPort(String httpsPort) { |
||||
this.httpsPort = httpsPort; |
||||
} |
||||
|
||||
public String getHttpPort() { |
||||
return httpPort; |
||||
} |
||||
|
||||
public void setHttpPort(String httpPort) { |
||||
this.httpPort = httpPort; |
||||
} |
||||
|
||||
public Long getConnectionTimeout() { |
||||
return connectionTimeout; |
||||
} |
||||
|
||||
public void setConnectionTimeout(Long connectionTimeout) { |
||||
this.connectionTimeout = connectionTimeout; |
||||
} |
||||
|
||||
public Long getReadTimeout() { |
||||
return readTimeout; |
||||
} |
||||
|
||||
public void setReadTimeout(Long readTimeout) { |
||||
this.readTimeout = readTimeout; |
||||
} |
||||
} |
@ -0,0 +1,102 @@ |
||||
package com.zilber.boot.dahua.controller; |
||||
|
||||
import com.dahuatech.hutool.http.Method; |
||||
import com.dahuatech.hutool.json.JSONUtil; |
||||
import com.dahuatech.icc.exception.ClientException; |
||||
import com.dahuatech.icc.oauth.model.v202010.OauthConfigUserPwdInfo; |
||||
import com.dahuatech.icc.oauth.utils.HttpUtils; |
||||
import com.zilber.boot.dahua.accesscontrol.QueryRecordRequest; |
||||
import com.zilber.boot.dahua.accesscontrol.QueryRecordResponse; |
||||
import com.zilber.boot.dahua.attendance.GetRecordPageRequest; |
||||
import com.zilber.boot.dahua.attendance.GetRecordPageResponse; |
||||
import com.zilber.boot.dahua.attendance.GetResultPageRequest; |
||||
import com.zilber.boot.dahua.attendance.GetResultPageResponse; |
||||
import com.zilber.boot.dahua.config.OauthConfigUtil; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.RequestBody; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
@RestController |
||||
@Api(tags = "大华接口") |
||||
@RequestMapping("/dahua") |
||||
@Slf4j |
||||
public class DahuaController { |
||||
|
||||
/** |
||||
* 打卡记录查询 |
||||
* @param getRecordPageRequest |
||||
* @return |
||||
* @throws ClientException |
||||
* 参考API:https://open-icc.dahuatech.com/#/home?url=%3Fnav%3Dwiki%2Fevo-attendance%2Fatt_information.html%23%E6%89%93%E5%8D%A1%E8%AE%B0%E5%BD%95%E6%9F%A5%E8%AF%A2&version=enterprisebase/5.0.16&blank=true
|
||||
*/ |
||||
@ApiOperation(value = "打卡记录查询",notes = "打卡记录查询") |
||||
@PostMapping("/attendance/getRecordPage") |
||||
public GetRecordPageResponse getAttendanceRecordPage(@RequestBody GetRecordPageRequest getRecordPageRequest) { |
||||
OauthConfigUserPwdInfo config = OauthConfigUtil.getOauthConfig(); |
||||
GetRecordPageResponse response=null; |
||||
try { |
||||
log.info("InfoQueryDemo,getAttendanceRecordPage,request:{}", JSONUtil.toJsonStr(getRecordPageRequest)); |
||||
response = HttpUtils.executeJson("/evo-apigw/evo-attendance/1.1.0/attendance/record/page", getRecordPageRequest,null, Method.POST , config, GetRecordPageResponse.class); |
||||
log.info("InfoQueryDemo,getAttendanceRecordPage,response:{}", JSONUtil.toJsonStr(response)); |
||||
} catch (ClientException e) { |
||||
log.error(e.getErrMsg(), e); |
||||
} |
||||
if(!response.isSuccess()) { |
||||
log.info("打卡记录查询失败:{}",response.getErrMsg()); |
||||
} |
||||
return response; |
||||
} |
||||
|
||||
/** |
||||
* 分页获取考勤结果 |
||||
* @param getResultPageRequest |
||||
* @return |
||||
* @throws ClientException |
||||
*/ |
||||
@ApiOperation(value = "分页获取考勤结果",notes = "分页获取考勤结果") |
||||
@PostMapping("/attendance/getResultPage") |
||||
public GetResultPageResponse getAttendanceResultPage(@RequestBody GetResultPageRequest getResultPageRequest) { |
||||
OauthConfigUserPwdInfo config = OauthConfigUtil.getOauthConfig(); |
||||
GetResultPageResponse response=null; |
||||
try { |
||||
log.info("InfoQueryDemo,getAttendanceRecordPage,request:{}", JSONUtil.toJsonStr(getResultPageRequest)); |
||||
response = HttpUtils.executeJson("/evo-apigw/evo-attendance/1.1.0/attendance/result/page", getResultPageRequest,null, Method.POST , config, GetResultPageResponse.class); |
||||
log.info("InfoQueryDemo,getAttendanceRecordPage,response:{}", JSONUtil.toJsonStr(response)); |
||||
} catch (ClientException e) { |
||||
log.error(e.getErrMsg(), e); |
||||
} |
||||
if(!response.isSuccess()) { |
||||
log.info("分页获取考勤结果失败:{}",response.getErrMsg()); |
||||
} |
||||
return response; |
||||
} |
||||
|
||||
/** |
||||
* 门禁 |
||||
* @return |
||||
* @throws ClientException |
||||
* 参考API:https://open-icc.dahuatech.com/#/home?url=%3Fnav%3Dwiki%2Fevo-accesscontrol%2Fevent.html&version=enterprisebase/5.0.16&blank=true
|
||||
*/ |
||||
@ApiOperation(value = "门禁记录查询",notes = "门禁记录查询") |
||||
@PostMapping("/accessControl/getRecordPage") |
||||
public QueryRecordResponse getRecordPage(@RequestBody QueryRecordRequest queryRecordRequest){ |
||||
OauthConfigUserPwdInfo config = OauthConfigUtil.getOauthConfig(); |
||||
QueryRecordResponse response=null; |
||||
try { |
||||
log.info("DeviceDemo,getRecordPage,request:{}", JSONUtil.toJsonStr(queryRecordRequest)); |
||||
response = HttpUtils.executeJson("/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/swingCardRecord/bycondition/combined", queryRecordRequest,null, Method.POST , config, QueryRecordResponse.class); |
||||
log.info("DeviceDemo,getRecordPage,response:{}", JSONUtil.toJsonStr(response)); |
||||
} catch (ClientException e) { |
||||
log.error(e.getErrMsg(), e); |
||||
} |
||||
if(!response.isSuccess()) { |
||||
log.info("门禁记录分页查询失败:{}",response.getErrMsg()); |
||||
} |
||||
return response; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue