小区改造

master
zzy 2026-04-20 16:45:24 +08:00
parent 0e997cfd5a
commit 51d7d8bdb3
7 changed files with 397 additions and 39 deletions

View File

@ -6,22 +6,23 @@ import com.fjrcloud.community.framework.common.pojo.PageParam;
import com.fjrcloud.community.framework.common.pojo.PageResult;
import com.fjrcloud.community.framework.common.util.object.BeanUtils;
import com.fjrcloud.community.framework.excel.core.util.ExcelUtils;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityPageReqVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityRespVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunitySaveReqVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.*;
import com.fjrcloud.community.module.community.dal.dataobject.community.CommunityDO;
import com.fjrcloud.community.module.community.service.community.CommunityService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static com.fjrcloud.community.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@ -98,4 +99,47 @@ public class CommunityController {
BeanUtils.toBean(list, CommunityRespVO.class));
}
@GetMapping("/get-import-template")
@Operation(summary = "获得导入小区模板")
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<CommunityImportExcelVO> list = Arrays.asList(
CommunityImportExcelVO.builder()
.communityName("阳光小区")
.streetName("幸福街道")
.districtName("和谐社区")
.communityAddress("阳光路 1 号")
.username("ygxq")
.password("123456")
.visitAuditStr("需要审核")
.gateAuditStr("需要审核")
.build(),
CommunityImportExcelVO.builder()
.communityName("月亮湾小区")
.streetName("平安街道")
.districtName("光明社区")
.communityAddress("月亮湾路 88 号")
.username("ylwxq")
.password("123456")
.visitAuditStr("无需审核")
.gateAuditStr("无需审核")
.build()
);
// 输出
ExcelUtils.write(response, "小区导入模板.xls", "小区列表", CommunityImportExcelVO.class, list);
}
@PostMapping("/import")
@Operation(summary = "导入小区")
@Parameters({
@Parameter(name = "file", description = "Excel 文件", required = true),
@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
})
@PreAuthorize("@ss.hasPermission('community:community:import')")
public CommonResult<CommunityImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
List<CommunityImportExcelVO> list = ExcelUtils.read(file, CommunityImportExcelVO.class);
return success(communityService.importCommunityList(list, updateSupport));
}
}

View File

@ -0,0 +1,53 @@
package com.fjrcloud.community.module.community.controller.admin.community.vo;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* Excel VO
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CommunityImportExcelVO {
@ExcelProperty("小区名称")
private String communityName;
@ExcelProperty("街道名称")
private String streetName;
@ExcelProperty("社区名称")
private String districtName;
@ExcelProperty("小区地址")
private String communityAddress;
@ExcelProperty("小区经度")
private BigDecimal longitude;
@ExcelProperty("小区纬度")
private BigDecimal latitude;
@ExcelProperty("小区物业")
private String propertyCompany;
@ExcelProperty("用户名")
private String username;
@ExcelProperty("密码")
private String password;
@ExcelProperty(value = "来访审核")
private String visitAuditStr;
@ExcelProperty(value = "道闸申请")
private String gateAuditStr;
}

View File

@ -0,0 +1,24 @@
package com.fjrcloud.community.module.community.controller.admin.community.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Schema(description = "管理后台 - 小区导入 Response VO")
@Data
@Builder
public class CommunityImportRespVO {
@Schema(description = "创建成功的小区名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> createCommunityNames;
@Schema(description = "更新成功的小区名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> updateCommunityNames;
@Schema(description = "导入失败的小区集合key 为小区名称value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
private Map<String, String> failureCommunities;
}

View File

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO;
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
import lombok.*;
import java.math.BigDecimal;
@ -22,7 +21,6 @@ import java.math.BigDecimal;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TenantIgnore
public class CommunityDO extends BaseDO {
/**
@ -76,4 +74,8 @@ public class CommunityDO extends BaseDO {
*/
private Boolean gateAudit;
/**
* ID
*/
private Long tenantId;
}

View File

@ -11,8 +11,11 @@ public interface ErrorCodeConstants {
ErrorCode COMMUNITY_NOT_EXISTS = new ErrorCode(2_001_000_001, "小区信息主表comm_community不存在");
ErrorCode COMMUNITY_IMPORT_LIST_IS_EMPTY = new ErrorCode(2_001_000_002, "导入小区数据不能为空!");
ErrorCode COMMUNITY_NAME_DUPLICATE = new ErrorCode(2_001_000_003, "小区名称【{}】已存在");
ErrorCode HOUSE_NOT_EXISTS = new ErrorCode(2_001_001_001, "房屋信息主不存在");
ErrorCode HOUSE_IMPORT_LIST_IS_EMPTY = new ErrorCode(2_001_001_002, "导入房屋数据不能为空!");
}

View File

@ -1,6 +1,8 @@
package com.fjrcloud.community.module.community.service.community;
import com.fjrcloud.community.framework.common.pojo.PageResult;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityImportExcelVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityImportRespVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityPageReqVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunitySaveReqVO;
import com.fjrcloud.community.module.community.dal.dataobject.community.CommunityDO;
@ -60,4 +62,13 @@ public interface CommunityService {
*/
PageResult<CommunityDO> getCommunityPage(CommunityPageReqVO pageReqVO);
/**
*
*
* @param importCommunities
* @param isUpdateSupport
* @return
*/
CommunityImportRespVO importCommunityList(List<CommunityImportExcelVO> importCommunities, boolean isUpdateSupport);
}

View File

@ -1,8 +1,14 @@
package com.fjrcloud.community.module.community.service.community;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.common.pojo.PageResult;
import com.fjrcloud.community.framework.common.util.object.BeanUtils;
import com.fjrcloud.community.framework.tenant.core.context.TenantContextHolder;
import com.fjrcloud.community.framework.tenant.core.util.TenantUtils;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityImportExcelVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityImportRespVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunityPageReqVO;
import com.fjrcloud.community.module.community.controller.admin.community.vo.CommunitySaveReqVO;
import com.fjrcloud.community.module.community.dal.dataobject.community.CommunityDO;
@ -14,9 +20,13 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.fjrcloud.community.module.community.enums.ErrorCodeConstants.COMMUNITY_IMPORT_LIST_IS_EMPTY;
import static com.fjrcloud.community.module.community.enums.ErrorCodeConstants.COMMUNITY_NOT_EXISTS;
/**
@ -60,6 +70,7 @@ public class CommunityServiceImpl implements CommunityService {
// 创建小区记录ID与租户ID一致
CommunityDO community = BeanUtils.toBean(createReqVO, CommunityDO.class);
community.setId(tenantId);
community.setTenantId(tenantId);
communityMapper.insert(community);
return community.getId();
@ -67,58 +78,268 @@ public class CommunityServiceImpl implements CommunityService {
@Override
public void updateCommunity(CommunitySaveReqVO updateReqVO) {
// 校验小区存在
validateCommunityExists(updateReqVO.getId());
// 校验小区存在且获取小区信息
CommunityDO existCommunity = validateCommunityExists(updateReqVO.getId());
// 更新租户信息
TenantSaveReqVO tenantReqVO = new TenantSaveReqVO();
tenantReqVO.setId(updateReqVO.getId());
tenantReqVO.setName(updateReqVO.getCommunityName());
tenantReqVO.setContactName(updateReqVO.getCommunityName());
tenantReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
tenantReqVO.setPackageId(TENANT_PACKAGE_ID);
tenantReqVO.setExpireTime(LocalDateTime.now().plusYears(100));
tenantReqVO.setAccountCount(9999);
Long currentTenantId = TenantContextHolder.getTenantId();
boolean isSystemTenant = Long.valueOf(1L).equals(currentTenantId);
tenantService.updateTenant(tenantReqVO);
// 非超管只能修改自己租户下的小区(使用 Objects.equals 防止 NPE
if (!isSystemTenant && !java.util.Objects.equals(currentTenantId, existCommunity.getTenantId())) {
throw exception(COMMUNITY_NOT_EXISTS);
}
// 更新小区信息
CommunityDO updateObj = BeanUtils.toBean(updateReqVO, CommunityDO.class);
communityMapper.updateById(updateObj);
// 提取公共更新逻辑
Runnable updateAction = () -> {
TenantSaveReqVO tenantReqVO = new TenantSaveReqVO();
tenantReqVO.setId(updateReqVO.getId());
tenantReqVO.setName(updateReqVO.getCommunityName());
tenantReqVO.setContactName(updateReqVO.getCommunityName());
tenantReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
tenantReqVO.setPackageId(TENANT_PACKAGE_ID);
tenantReqVO.setExpireTime(LocalDateTime.now().plusYears(100));
tenantReqVO.setAccountCount(9999);
tenantService.updateTenant(tenantReqVO);
CommunityDO updateObj = BeanUtils.toBean(updateReqVO, CommunityDO.class);
communityMapper.updateById(updateObj);
};
if (isSystemTenant) {
TenantUtils.executeIgnore(updateAction);
} else {
updateAction.run();
}
}
@Override
public void deleteCommunity(Long id) {
// 校验小区存在
validateCommunityExists(id);
// 删除小区
communityMapper.deleteById(id);
// 同步删除租户
tenantService.deleteTenant(id);
}
// 校验小区存在且获取小区信息
CommunityDO existCommunity = validateCommunityExists(id);
@Override
public void deleteCommunityListByIds(List<Long> ids) {
// 批量删除小区
communityMapper.deleteByIds(ids);
// 同步删除租户
ids.forEach(id -> tenantService.deleteTenant(id));
}
// 非超管只能删除自己租户下的小区
Long currentTenantId = TenantContextHolder.getTenantId();
if (!Long.valueOf(1).equals(currentTenantId)) {
if (!existCommunity.getTenantId().equals(currentTenantId)) {
throw exception(COMMUNITY_NOT_EXISTS);
}
}
private void validateCommunityExists(Long id) {
if (communityMapper.selectById(id) == null) {
throw exception(COMMUNITY_NOT_EXISTS);
// 超管删除时忽略租户隔离,租户管理员删除时框架自动处理
if (Long.valueOf(1).equals(currentTenantId)) {
TenantUtils.executeIgnore(() -> {
// 删除小区
communityMapper.deleteById(id);
// 同步删除租户
tenantService.deleteTenant(id);
});
} else {
// 删除小区
communityMapper.deleteById(id);
// 同步删除租户
tenantService.deleteTenant(id);
}
}
@Override
public void deleteCommunityListByIds(List<Long> ids) {
Long currentTenantId = TenantContextHolder.getTenantId();
// 超管批量删除时忽略租户隔离
if (Long.valueOf(1).equals(currentTenantId)) {
TenantUtils.executeIgnore(() -> {
communityMapper.deleteByIds(ids);
ids.forEach(id -> tenantService.deleteTenant(id));
});
} else {
// 批量删除小区
communityMapper.deleteByIds(ids);
// 同步删除租户
ids.forEach(id -> tenantService.deleteTenant(id));
}
}
private CommunityDO validateCommunityExists(Long id) {
CommunityDO community;
// 超管查询时忽略租户隔离
if (Long.valueOf(1).equals(TenantContextHolder.getTenantId())) {
community = TenantUtils.executeIgnore(() -> communityMapper.selectById(id));
} else {
community = communityMapper.selectById(id);
}
if (community == null) {
throw exception(COMMUNITY_NOT_EXISTS);
}
return community;
}
@Override
public CommunityDO getCommunity(Long id) {
return communityMapper.selectById(id);
CommunityDO community;
// 超管查询时忽略租户隔离
if (Long.valueOf(1).equals(TenantContextHolder.getTenantId())) {
community = TenantUtils.executeIgnore(() -> communityMapper.selectById(id));
} else {
community = communityMapper.selectById(id);
}
return community;
}
@Override
public PageResult<CommunityDO> getCommunityPage(CommunityPageReqVO pageReqVO) {
// 超管系统租户ID为1登录时查询所有小区忽略租户隔离
// 租户管理员登录时,框架的 MyBatis-Plus 租户插件会自动加上 tenant_id 条件过滤当前租户数据
if (Long.valueOf(1).equals(TenantContextHolder.getTenantId())) {
return TenantUtils.executeIgnore(() -> communityMapper.selectPage(pageReqVO));
}
return communityMapper.selectPage(pageReqVO);
}
@Override
public CommunityImportRespVO importCommunityList(List<CommunityImportExcelVO> importCommunities, boolean isUpdateSupport) {
// 1. 参数校验
if (CollUtil.isEmpty(importCommunities)) {
throw exception(COMMUNITY_IMPORT_LIST_IS_EMPTY);
}
// 2. 遍历,逐个创建 or 更新
CommunityImportRespVO respVO = CommunityImportRespVO.builder()
.createCommunityNames(new ArrayList<>())
.updateCommunityNames(new ArrayList<>())
.failureCommunities(new LinkedHashMap<>())
.build();
AtomicInteger index = new AtomicInteger(1);
importCommunities.forEach(importCommunity -> {
int currentIndex = index.getAndIncrement();
// 2.1 校验必填字段
try {
validateImportCommunity(importCommunity, currentIndex);
} catch (Exception ex) {
respVO.getFailureCommunities().put(importCommunity.getCommunityName() != null ? importCommunity.getCommunityName() : "第 " + currentIndex + " 行", ex.getMessage());
return;
}
// 2.2 转换 Boolean 值
Boolean visitAudit = convertBoolean(importCommunity.getVisitAuditStr());
Boolean gateAudit = convertBoolean(importCommunity.getGateAuditStr());
// 2.3 判断小区是否已存在
CommunityDO existCommunity = findCommunityByName(importCommunity.getCommunityName());
// 2.4 如果不存在,进行插入
if (existCommunity == null) {
try {
CommunitySaveReqVO createReqVO = new CommunitySaveReqVO();
createReqVO.setCommunityName(importCommunity.getCommunityName());
createReqVO.setStreetName(importCommunity.getStreetName());
createReqVO.setDistrictName(importCommunity.getDistrictName());
createReqVO.setCommunityAddress(importCommunity.getCommunityAddress());
createReqVO.setLongitude(importCommunity.getLongitude());
createReqVO.setLatitude(importCommunity.getLatitude());
createReqVO.setPropertyCompany(importCommunity.getPropertyCompany());
createReqVO.setUsername(importCommunity.getUsername());
createReqVO.setPassword(importCommunity.getPassword());
createReqVO.setVisitAudit(visitAudit);
createReqVO.setGateAudit(gateAudit);
createCommunity(createReqVO);
respVO.getCreateCommunityNames().add(importCommunity.getCommunityName());
} catch (Exception e) {
respVO.getFailureCommunities().put(importCommunity.getCommunityName(), e.getMessage());
}
return;
}
// 2.5 如果存在,判断是否允许更新
if (!isUpdateSupport) {
respVO.getFailureCommunities().put(importCommunity.getCommunityName(), "小区已存在,且不支持更新");
return;
}
// 2.6 更新已有小区
try {
CommunitySaveReqVO updateReqVO = new CommunitySaveReqVO();
updateReqVO.setId(existCommunity.getId());
updateReqVO.setCommunityName(importCommunity.getCommunityName());
updateReqVO.setStreetName(importCommunity.getStreetName());
updateReqVO.setDistrictName(importCommunity.getDistrictName());
updateReqVO.setCommunityAddress(importCommunity.getCommunityAddress());
updateReqVO.setLongitude(importCommunity.getLongitude());
updateReqVO.setLatitude(importCommunity.getLatitude());
updateReqVO.setPropertyCompany(importCommunity.getPropertyCompany());
updateReqVO.setVisitAudit(visitAudit);
updateReqVO.setGateAudit(gateAudit);
updateCommunity(updateReqVO);
respVO.getUpdateCommunityNames().add(importCommunity.getCommunityName());
} catch (Exception e) {
respVO.getFailureCommunities().put(importCommunity.getCommunityName(), e.getMessage());
}
});
return respVO;
}
/**
*
*/
private void validateImportCommunity(CommunityImportExcelVO importCommunity, int currentIndex) {
if (StrUtil.isBlank(importCommunity.getCommunityName())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:小区名称不能为空");
}
if (StrUtil.isBlank(importCommunity.getStreetName())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:街道名称不能为空");
}
if (StrUtil.isBlank(importCommunity.getDistrictName())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:社区名称不能为空");
}
if (StrUtil.isBlank(importCommunity.getCommunityAddress())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:小区地址不能为空");
}
if (StrUtil.isBlank(importCommunity.getUsername())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:用户名不能为空");
}
if (StrUtil.isBlank(importCommunity.getPassword())) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:密码不能为空");
}
if (importCommunity.getVisitAuditStr() == null) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:来访审核不能为空");
}
if (importCommunity.getGateAuditStr() == null) {
throw new IllegalArgumentException("第 " + currentIndex + " 行:道闸申请不能为空");
}
}
/**
* Boolean
* ->true, ->false, 1->true, 0->false
*/
private Boolean convertBoolean(String str) {
if (str == null) {
return false;
}
if ("需要审核".equals(str) || "1".equals(str) || "true".equalsIgnoreCase(str)) {
return true;
}
return false;
}
/**
*
*/
private CommunityDO findCommunityByName(String communityName) {
// 超管查询时忽略租户隔离
if (Long.valueOf(1).equals(TenantContextHolder.getTenantId())) {
return TenantUtils.executeIgnore(() ->
communityMapper.selectOne(CommunityDO::getCommunityName, communityName)
);
}
return communityMapper.selectOne(CommunityDO::getCommunityName, communityName);
}
}