mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-01-25 07:46:40 +08:00
feat(smartCam): 添加车辆出入记录功能
- 新增 SmartCamCarData 模块,用于记录车辆出入信息 - 在 SmartCamCarLicenseSnapshotData 中添加方向字段 - 实现车辆出入记录的创建、更新、删除和查询功能 - 添加字典翻译支持,用于摄像头方向描述
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package cn.lihongjie.coal.smartCam.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
import cn.lihongjie.coal.pojoProcessor.DictTranslate;
|
||||
import cn.lihongjie.coal.smartCamSupplier.dto.SmartCamSupplierDto;
|
||||
|
||||
import jakarta.persistence.ManyToOne;
|
||||
@@ -19,4 +20,7 @@ public class SmartCamDto extends OrgCommonDto {
|
||||
|
||||
@Comment("摄像头方向")
|
||||
private String direction;
|
||||
|
||||
@DictTranslate(dictKey = "smartCam.dir")
|
||||
private String directionName;
|
||||
}
|
||||
|
||||
@@ -35,4 +35,5 @@ public class SmartCamEntity extends OrgCommonEntity {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.controller;
|
||||
|
||||
import cn.lihongjie.coal.annotation.OrgScope;
|
||||
import cn.lihongjie.coal.annotation.SysLog;
|
||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.CreateSmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.SmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.UpdateSmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.service.SmartCamCarDataService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
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
|
||||
@RequestMapping("/smartCamCarData")
|
||||
@SysLog(module = "智能摄像头车辆出入记录")
|
||||
@Slf4j
|
||||
@OrgScope
|
||||
public class SmartCamCarDataController {
|
||||
@Autowired private SmartCamCarDataService service;
|
||||
|
||||
@PostMapping("/create")
|
||||
public SmartCamCarDataDto create(@RequestBody CreateSmartCamCarDataDto request) {
|
||||
return this.service.create(request);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public SmartCamCarDataDto update(@RequestBody UpdateSmartCamCarDataDto request) {
|
||||
return this.service.update(request);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public Object delete(@RequestBody IdRequest request) {
|
||||
this.service.delete(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("/getById")
|
||||
public SmartCamCarDataDto getById(@RequestBody IdRequest request) {
|
||||
return this.service.getById(request.getId());
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
public Page<SmartCamCarDataDto> list(@RequestBody CommonQuery request) {
|
||||
return this.service.list(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateSmartCamCarDataDto extends OrgCommonDto {}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
import cn.lihongjie.coal.smartCamCarLicenseSnapshotData.dto.SmartCamCarLicenseSnapshotDataDto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class SmartCamCarDataDto extends OrgCommonDto {
|
||||
|
||||
private String number;
|
||||
|
||||
private LocalDateTime entryTime;
|
||||
|
||||
private LocalDateTime exitTime;
|
||||
|
||||
private SmartCamCarLicenseSnapshotDataDto entry;
|
||||
|
||||
private SmartCamCarLicenseSnapshotDataDto exit;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UpdateSmartCamCarDataDto extends OrgCommonDto {}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.entity;
|
||||
|
||||
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
|
||||
import cn.lihongjie.coal.smartCamCarLicenseSnapshotData.entity.SmartCamCarLicenseSnapshotDataEntity;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(
|
||||
indexes =
|
||||
@jakarta.persistence.Index(
|
||||
name = "idx_smartCamCarData_org_id",
|
||||
columnList = "organization_id"))
|
||||
public class SmartCamCarDataEntity extends OrgCommonEntity {
|
||||
|
||||
|
||||
private String number;
|
||||
|
||||
private LocalDateTime entryTime;
|
||||
|
||||
private LocalDateTime exitTime;
|
||||
|
||||
|
||||
|
||||
@ManyToOne
|
||||
private SmartCamCarLicenseSnapshotDataEntity entry;
|
||||
|
||||
|
||||
@ManyToOne
|
||||
private SmartCamCarLicenseSnapshotDataEntity exit;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.mapper;
|
||||
|
||||
import cn.lihongjie.coal.base.mapper.BaseMapper;
|
||||
import cn.lihongjie.coal.base.mapper.CommonEntityMapper;
|
||||
import cn.lihongjie.coal.base.mapper.CommonMapper;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.CreateSmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.SmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.UpdateSmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.entity.SmartCamCarDataEntity;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.control.DeepClone;
|
||||
|
||||
@Mapper(
|
||||
componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING,
|
||||
uses = {CommonMapper.class, CommonEntityMapper.class},
|
||||
mappingControl = DeepClone.class)
|
||||
public interface SmartCamCarDataMapper
|
||||
extends BaseMapper<
|
||||
SmartCamCarDataEntity,
|
||||
SmartCamCarDataDto,
|
||||
CreateSmartCamCarDataDto,
|
||||
UpdateSmartCamCarDataDto> {}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.repository;
|
||||
|
||||
import cn.lihongjie.coal.base.dao.BaseRepository;
|
||||
import cn.lihongjie.coal.smartCamCarData.entity.SmartCamCarDataEntity;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface SmartCamCarDataRepository extends BaseRepository<SmartCamCarDataEntity> {
|
||||
@Query("select false")
|
||||
boolean isLinked(List<String> ids);
|
||||
|
||||
@Query("select d from SmartCamCarDataEntity d where d.number = :number and d.organizationId = :organizationId order by d.createTime desc limit 1")
|
||||
SmartCamCarDataEntity findByNumber(String organizationId, String number);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.lihongjie.coal.smartCamCarData.service;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||
import cn.lihongjie.coal.base.service.BaseService;
|
||||
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
|
||||
import cn.lihongjie.coal.exception.BizException;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.CreateSmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.SmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.dto.UpdateSmartCamCarDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarData.entity.SmartCamCarDataEntity;
|
||||
import cn.lihongjie.coal.smartCamCarData.mapper.SmartCamCarDataMapper;
|
||||
import cn.lihongjie.coal.smartCamCarData.repository.SmartCamCarDataRepository;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional
|
||||
public class SmartCamCarDataService
|
||||
extends BaseService<SmartCamCarDataEntity, SmartCamCarDataRepository> {
|
||||
@Autowired private SmartCamCarDataRepository repository;
|
||||
|
||||
@Autowired private SmartCamCarDataMapper mapper;
|
||||
|
||||
@Autowired private ConversionService conversionService;
|
||||
|
||||
@Autowired private DbFunctionService dbFunctionService;
|
||||
|
||||
public SmartCamCarDataDto create(CreateSmartCamCarDataDto request) {
|
||||
SmartCamCarDataEntity entity = mapper.toEntity(request);
|
||||
|
||||
this.repository.save(entity);
|
||||
return getById(entity.getId());
|
||||
}
|
||||
|
||||
public SmartCamCarDataDto update(UpdateSmartCamCarDataDto request) {
|
||||
SmartCamCarDataEntity entity = this.repository.get(request.getId());
|
||||
this.mapper.updateEntity(entity, request);
|
||||
|
||||
this.repository.save(entity);
|
||||
|
||||
return getById(entity.getId());
|
||||
}
|
||||
|
||||
public void delete(IdRequest request) {
|
||||
boolean linked = this.repository.isLinked(request.getIds());
|
||||
|
||||
if (linked) {
|
||||
throw new BizException("数据已被关联,无法删除");
|
||||
}
|
||||
|
||||
this.repository.deleteAllById(request.getIds());
|
||||
}
|
||||
|
||||
public SmartCamCarDataDto getById(String id) {
|
||||
SmartCamCarDataEntity entity = repository.get(id);
|
||||
|
||||
return mapper.toDto(entity);
|
||||
}
|
||||
|
||||
public Page<SmartCamCarDataDto> list(CommonQuery query) {
|
||||
Page<SmartCamCarDataEntity> page =
|
||||
repository.findAll(
|
||||
query.specification(conversionService),
|
||||
PageRequest.of(
|
||||
query.getPageNo(),
|
||||
query.getPageSize(),
|
||||
Sort.by(query.getOrders())));
|
||||
|
||||
return page.map(this.mapper::toDto);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import cn.lihongjie.coal.file.entity.FileEntity;
|
||||
import cn.lihongjie.coal.file.service.FileService;
|
||||
import cn.lihongjie.coal.smartCam.entity.SmartCamEntity;
|
||||
import cn.lihongjie.coal.smartCam.service.SmartCamService;
|
||||
import cn.lihongjie.coal.smartCamCarData.entity.SmartCamCarDataEntity;
|
||||
import cn.lihongjie.coal.smartCamCarData.repository.SmartCamCarDataRepository;
|
||||
import cn.lihongjie.coal.smartCamCarLicenseSnapshotData.dto.CreateSmartCamCarLicenseSnapshotDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarLicenseSnapshotData.dto.SmartCamCarLicenseSnapshotDataDto;
|
||||
import cn.lihongjie.coal.smartCamCarLicenseSnapshotData.dto.UpdateSmartCamCarLicenseSnapshotDataDto;
|
||||
@@ -24,6 +26,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -36,6 +42,7 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -58,6 +65,8 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
@Autowired private ConversionService conversionService;
|
||||
@Autowired private DbFunctionService dbFunctionService;
|
||||
|
||||
@Autowired private SmartCamCarDataRepository smartCamCarDataRepository;
|
||||
|
||||
public SmartCamCarLicenseSnapshotDataDto create(
|
||||
CreateSmartCamCarLicenseSnapshotDataDto request) {
|
||||
SmartCamCarLicenseSnapshotDataEntity entity = mapper.toEntity(request);
|
||||
@@ -93,9 +102,29 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
}
|
||||
|
||||
public Page<SmartCamCarLicenseSnapshotDataDto> list(CommonQuery query) {
|
||||
Specification specification = query.specification(conversionService);
|
||||
|
||||
if (Boolean.parseBoolean(query.get("ignoreEmptyNumber", "true"))) {
|
||||
|
||||
specification =
|
||||
specification.and(
|
||||
new Specification() {
|
||||
@Override
|
||||
public Predicate toPredicate(
|
||||
Root root,
|
||||
CriteriaQuery query,
|
||||
CriteriaBuilder criteriaBuilder) {
|
||||
|
||||
return criteriaBuilder.and(
|
||||
criteriaBuilder.notEqual(root.get("number"), ""),
|
||||
criteriaBuilder.isNotNull(root.get("number")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Page<SmartCamCarLicenseSnapshotDataEntity> page =
|
||||
repository.findAll(
|
||||
query.specification(conversionService),
|
||||
specification,
|
||||
PageRequest.of(
|
||||
query.getPageNo(),
|
||||
query.getPageSize(),
|
||||
@@ -107,18 +136,14 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
@SneakyThrows
|
||||
public ObjectNode saveEvent(String json) {
|
||||
|
||||
// log.info("saveEvent {}", json);
|
||||
// log.info("saveEvent {}", json);
|
||||
JsonNode rootNode = objectMapper.readTree(json);
|
||||
SmartCamCarLicenseSnapshotDataEntity entity = new SmartCamCarLicenseSnapshotDataEntity();
|
||||
|
||||
// Operator
|
||||
entity.setOperator(rootNode.path("operator").asText());
|
||||
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(entity.getOperator(), "heartbeat")){
|
||||
|
||||
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(entity.getOperator(), "heartbeat")) {
|
||||
|
||||
return getHeartbeatAck(rootNode);
|
||||
}
|
||||
@@ -226,7 +251,8 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
|
||||
+ "_"
|
||||
+ "plate",
|
||||
"car_license_snapshot", smartCam.getOrganizationId());
|
||||
"car_license_snapshot",
|
||||
smartCam.getOrganizationId());
|
||||
|
||||
entity.setCaptureImage(em.getReference(FileEntity.class, captureDto.getId()));
|
||||
}
|
||||
@@ -247,7 +273,8 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
|
||||
+ "_"
|
||||
+ "bg",
|
||||
"car_license_snapshot", smartCam.getOrganizationId());
|
||||
"car_license_snapshot",
|
||||
smartCam.getOrganizationId());
|
||||
|
||||
entity.setBackgroundImage(em.getReference(FileEntity.class, backgroundDto.getId()));
|
||||
}
|
||||
@@ -270,9 +297,65 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
|
||||
ObjectNode objectNode = getAck(entity.getInfoEventId());
|
||||
|
||||
saveCarData(entity);
|
||||
|
||||
return objectNode;
|
||||
}
|
||||
|
||||
private void saveCarData(SmartCamCarLicenseSnapshotDataEntity entity) {
|
||||
|
||||
try {
|
||||
|
||||
if (StringUtils.isEmpty(entity.getNumber())) {
|
||||
|
||||
log.info("车牌号为空");
|
||||
return;
|
||||
}
|
||||
|
||||
SmartCamCarDataEntity byNumber =
|
||||
smartCamCarDataRepository.findByNumber(
|
||||
entity.getOrganizationId(), entity.getNumber());
|
||||
|
||||
boolean entry = StringUtils.equals(entity.getSmartCam().getDirection(), "0");
|
||||
if (byNumber == null) {
|
||||
|
||||
if (entry) {
|
||||
|
||||
SmartCamCarDataEntity smartCamCarDataEntity = new SmartCamCarDataEntity();
|
||||
smartCamCarDataEntity.setNumber(entity.getNumber());
|
||||
smartCamCarDataEntity.setEntry(entity);
|
||||
smartCamCarDataEntity.setEntryTime(entity.getInfoTimeObj());
|
||||
|
||||
smartCamCarDataRepository.save(smartCamCarDataEntity);
|
||||
|
||||
} else {
|
||||
|
||||
SmartCamCarDataEntity smartCamCarDataEntity = new SmartCamCarDataEntity();
|
||||
smartCamCarDataEntity.setNumber(entity.getNumber());
|
||||
smartCamCarDataEntity.setExit(entity);
|
||||
smartCamCarDataEntity.setExitTime(entity.getInfoTimeObj());
|
||||
smartCamCarDataRepository.save(smartCamCarDataEntity);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (entry) {
|
||||
|
||||
log.info("重复的车牌号数据 {} {}", byNumber.getId(), byNumber.getNumber());
|
||||
|
||||
} else {
|
||||
|
||||
byNumber.setExit(entity);
|
||||
byNumber.setExitTime(entity.getInfoTimeObj());
|
||||
|
||||
smartCamCarDataRepository.save(byNumber);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("保存数据异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private ObjectNode getHeartbeatAck(JsonNode rootNode) {
|
||||
|
||||
@@ -287,8 +370,10 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
* true, "isCarDetectEnable": true, "isMotionDetectEnable": true } }, "result": { "errorNo":
|
||||
* 0, "description": "ok" } }
|
||||
*/
|
||||
ObjectNode jsonNode = (ObjectNode) objectMapper.readTree(
|
||||
"""
|
||||
ObjectNode jsonNode =
|
||||
(ObjectNode)
|
||||
objectMapper.readTree(
|
||||
"""
|
||||
{
|
||||
"operator": "heartbeat-Ack",
|
||||
"info": {
|
||||
@@ -325,14 +410,9 @@ public class SmartCamCarLicenseSnapshotDataService
|
||||
((ObjectNode) jsonNode.get("info"))
|
||||
.put("eventId", rootNode.get("info").get("eventId").asInt());
|
||||
|
||||
((ObjectNode) jsonNode.get("info"))
|
||||
.put("time", rootNode.get("info").get("time").asInt());
|
||||
|
||||
((ObjectNode) jsonNode.get("info"))
|
||||
.put("heartbeatInterval", 300);
|
||||
|
||||
|
||||
((ObjectNode) jsonNode.get("info")).put("time", rootNode.get("info").get("time").asInt());
|
||||
|
||||
((ObjectNode) jsonNode.get("info")).put("heartbeatInterval", 300);
|
||||
|
||||
jsonNode.put("operator", "heartbeat-Ack");
|
||||
|
||||
|
||||
@@ -2864,5 +2864,22 @@
|
||||
"name": "其他"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"code": "smartCam.dir",
|
||||
"name": "智能摄像头方向",
|
||||
"item": [
|
||||
{
|
||||
"code": "0",
|
||||
"name": "入口"
|
||||
},
|
||||
{
|
||||
"code": "1",
|
||||
"name": "出口"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
package scripts.dict
|
||||
|
||||
import cn.lihongjie.coal.base.dto.CommonQuery
|
||||
import cn.lihongjie.coal.smartCamCarData.controller.SmartCamCarDataController
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import org.springframework.context.ApplicationContext
|
||||
|
||||
ApplicationContext ioc = ioc
|
||||
|
||||
def controller = ioc.getBean(SmartCamCarDataController.class)
|
||||
def objectMapper = ioc.getBean(ObjectMapper.class) as ObjectMapper
|
||||
|
||||
|
||||
|
||||
|
||||
return controller.list(params!=null ? objectMapper.convertValue(params, CommonQuery.class ) : new CommonQuery())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user