当前位置: 首页 > article >正文

Java全栈项目 - 智能小区物业管理平台开发实践

一、项目介绍

智能小区物业管理平台是一个基于 Java 全栈技术开发的现代化物业管理系统。该平台旨在提供完整的物业管理解决方案,实现小区管理的智能化和信息化。

1.1 项目背景

随着城市化进程加快,现代小区物业管理面临着以下挑战:

  • 传统人工管理效率低下
  • 信息沟通不畅
  • 服务质量难以保证
  • 收费管理复杂

1.2 主要功能

  • 住户管理
  • 物业费用管理
  • 停车场管理
  • 报修管理
  • 公告管理
  • 访客管理
  • 投诉建议
  • 统计分析

二、技术架构

2.1 后端技术栈

  • 核心框架:Spring Boot 2.x
  • 持久层:MyBatis-Plus
  • 权限认证:Spring Security + JWT
  • 数据库:MySQL 8.0
  • 缓存:Redis
  • 消息队列:RabbitMQ
  • 文件存储:阿里云 OSS

2.2 前端技术栈

  • 框架:Vue.js 3.0
  • UI组件:Element Plus
  • 状态管理:Vuex 4
  • 路由:Vue Router 4
  • HTTP客户端:Axios
  • 图表:ECharts

三、核心功能实现

3.1 住户管理模块

@Service
public class ResidentServiceImpl implements ResidentService {
    
    @Autowired
    private ResidentMapper residentMapper;
    
    @Override
    public PageResult<ResidentVO> queryResidents(ResidentQuery query) {
        // 构建查询条件
        LambdaQueryWrapper<Resident> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(query.getName()), 
                    Resident::getName, query.getName())
               .eq(query.getBuildingId() != null, 
                   Resident::getBuildingId, query.getBuildingId());
                   
        // 分页查询
        Page<Resident> page = residentMapper.selectPage(
            new Page<>(query.getPage(), query.getSize()), 
            wrapper
        );
        
        // 转换结果
        return PageResult.of(page, this::convertToVO);
    }
}

3.2 物业费用管理

@Service
@Transactional
public class PropertyFeeServiceImpl implements PropertyFeeService {
    
    @Autowired
    private PropertyFeeMapper feeMapper;
    
    @Override
    public void createBill(PropertyFeeBillDTO dto) {
        // 计算费用
        BigDecimal amount = calculateFeeAmount(dto);
        
        // 生成账单
        PropertyFeeBill bill = new PropertyFeeBill();
        bill.setResidentId(dto.getResidentId());
        bill.setAmount(amount);
        bill.setMonth(dto.getMonth());
        bill.setStatus(BillStatus.UNPAID);
        
        // 保存账单
        feeMapper.insert(bill);
        
        // 发送账单通知
        sendBillNotification(bill);
    }
}

3.3 报修管理

@RestController
@RequestMapping("/api/repair")
public class RepairController {
    
    @Autowired
    private RepairService repairService;
    
    @PostMapping("/submit")
    public Result<Void> submitRepair(@RequestBody RepairDTO dto) {
        // 参数校验
        validateRepairParams(dto);
        
        // 提交报修
        repairService.submitRepair(dto);
        
        return Result.success();
    }
    
    @GetMapping("/list")
    public Result<PageResult<RepairVO>> queryRepairs(RepairQuery query) {
        PageResult<RepairVO> result = repairService.queryRepairs(query);
        return Result.success(result);
    }
}

四、系统优化

4.1 性能优化

  1. 使用 Redis 缓存热点数据
@Cacheable(value = "resident", key = "#id")
public ResidentVO getResidentInfo(Long id) {
    Resident resident = residentMapper.selectById(id);
    return convertToVO(resident);
}
  1. 使用 MyBatis-Plus 分页插件优化查询

  2. 实现数据库读写分离

4.2 安全优化

  1. 实现基于 JWT 的认证授权
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .anyRequest().authenticated();
            
        http.addFilterBefore(jwtAuthFilter, 
            UsernamePasswordAuthenticationFilter.class);
    }
}
  1. 数据加密传输
  2. 防SQL注入
  3. XSS防护

五、项目部署

5.1 环境配置

  • JDK 1.8+
  • Maven 3.6+
  • MySQL 8.0
  • Redis 6.x
  • Nginx 1.18

5.2 部署架构

  • 采用前后端分离部署
  • 使用 Docker 容器化部署
  • 实现服务高可用

六、项目总结

6.1 技术亮点

  1. 采用主流的 Java 全栈技术栈
  2. 实现了完整的物业管理业务流程
  3. 良好的系统性能和安全性
  4. 支持高并发和分布式部署

6.2 未来展望

  1. 引入微服务架构
  2. 集成物联网设备
  3. 开发移动端应用
  4. 引入人工智能技术

通过本项目的开发实践,不仅实现了物业管理的信息化和智能化,也积累了丰富的全栈开发经验。

Java全栈项目 - 智能小区物业管理平台核心模块详解

一、住户管理模块

1.1 功能设计

  • 住户信息管理(新增、修改、查询、删除)
  • 房屋信息关联
  • 住户认证审核
  • 家庭成员管理
  • 住户档案管理

1.2 数据库设计

-- 住户信息表
CREATE TABLE t_resident (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL COMMENT '姓名',
    phone VARCHAR(20) NOT NULL COMMENT '手机号',
    id_card VARCHAR(18) NOT NULL COMMENT '身份证号',
    gender TINYINT COMMENT '性别:1-男,2-女',
    building_id BIGINT COMMENT '楼栋ID',
    unit_no VARCHAR(10) COMMENT '单元号',
    room_no VARCHAR(10) COMMENT '房间号',
    resident_type TINYINT COMMENT '住户类型:1-业主,2-租户',
    status TINYINT COMMENT '状态:0-待审核,1-正常,2-禁用',
    create_time DATETIME,
    update_time DATETIME
);

-- 家庭成员表
CREATE TABLE t_family_member (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    resident_id BIGINT COMMENT '住户ID',
    name VARCHAR(50) COMMENT '姓名',
    relation VARCHAR(20) COMMENT '与户主关系',
    phone VARCHAR(20) COMMENT '联系电话',
    create_time DATETIME
);

1.3 核心代码实现

// 住户实体类
@Data
@TableName("t_resident")
public class Resident {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private String phone;
    private String idCard;
    private Integer gender;
    private Long buildingId;
    private String unitNo;
    private String roomNo;
    private Integer residentType;
    private Integer status;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

// 住户服务接口
@Service
public class ResidentServiceImpl implements ResidentService {
    
    @Autowired
    private ResidentMapper residentMapper;
    
    @Override
    @Transactional
    public void addResident(ResidentDTO dto) {
        // 验证住户信息
        validateResidentInfo(dto);
        
        // 检查是否重复登记
        checkDuplicate(dto);
        
        // 构建实体并保存
        Resident resident = buildResident(dto);
        residentMapper.insert(resident);
        
        // 保存家庭成员信息
        saveFamilyMembers(resident.getId(), dto.getFamilyMembers());
        
        // 发送审核通知
        sendAuditNotification(resident);
    }
    
    @Override
    public PageResult<ResidentVO> queryResidents(ResidentQuery query) {
        LambdaQueryWrapper<Resident> wrapper = new LambdaQueryWrapper<>();
        // 构建查询条件
        wrapper.like(StringUtils.isNotBlank(query.getName()), 
                    Resident::getName, query.getName())
               .eq(query.getBuildingId() != null, 
                   Resident::getBuildingId, query.getBuildingId())
               .eq(query.getStatus() != null,
                   Resident::getStatus, query.getStatus());
                   
        // 分页查询
        Page<Resident> page = residentMapper.selectPage(
            new Page<>(query.getPage(), query.getSize()), 
            wrapper
        );
        
        // 转换并返回结果
        return PageResult.of(page, this::convertToVO);
    }
}

二、物业费用管理模块

2.1 功能设计

  • 费用项目管理
  • 费用标准设置
  • 账单生成
  • 缴费管理
  • 催缴通知
  • 费用统计

2.2 数据库设计

-- 费用项目表
CREATE TABLE t_fee_item (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    item_name VARCHAR(50) COMMENT '费用项目名称',
    charge_type TINYINT COMMENT '收费类型:1-按面积,2-按户,3-按用量',
    unit_price DECIMAL(10,2) COMMENT '单价',
    status TINYINT COMMENT '状态:1-启用,0-禁用'
);

-- 物业费账单表
CREATE TABLE t_property_bill (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    resident_id BIGINT COMMENT '住户ID',
    room_id BIGINT COMMENT '房间ID',
    bill_month VARCHAR(7) COMMENT '账单月份',
    total_amount DECIMAL(10,2) COMMENT '总金额',
    status TINYINT COMMENT '状态:0-待缴费,1-已缴费,2-逾期',
    payment_time DATETIME COMMENT '缴费时间',
    create_time DATETIME,
    due_time DATETIME COMMENT '截止时间'
);

-- 账单明细表
CREATE TABLE t_bill_detail (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    bill_id BIGINT COMMENT '账单ID',
    fee_item_id BIGINT COMMENT '费用项目ID',
    amount DECIMAL(10,2) COMMENT '金额',
    unit_price DECIMAL(10,2) COMMENT '单价',
    quantity DECIMAL(10,2) COMMENT '数量'
);

2.3 核心代码实现

@Service
@Transactional
public class PropertyFeeServiceImpl implements PropertyFeeService {
    
    @Autowired
    private PropertyBillMapper billMapper;
    @Autowired
    private BillDetailMapper detailMapper;
    
    @Override
    public void generateMonthlyBills() {
        // 获取所有有效住户
        List<Resident> residents = residentMapper.selectValidResidents();
        
        // 获取费用项目
        List<FeeItem> feeItems = feeItemMapper.selectValidItems();
        
        // 批量生成账单
        for (Resident resident : residents) {
            PropertyBill bill = new PropertyBill();
            bill.setResidentId(resident.getId());
            bill.setRoomId(resident.getRoomId());
            bill.setBillMonth(DateUtil.getCurrentMonth());
            bill.setStatus(BillStatus.UNPAID.getCode());
            
            // 计算各项费用
            List<BillDetail> details = calculateFeeDetails(resident, feeItems);
            BigDecimal totalAmount = calculateTotalAmount(details);
            bill.setTotalAmount(totalAmount);
            
            // 保存账单及明细
            billMapper.insert(bill);
            saveBillDetails(bill.getId(), details);
            
            // 发送账单通知
            sendBillNotification(resident, bill);
        }
    }
    
    @Override
    public void payBill(PaymentDTO dto) {
        // 查询账单
        PropertyBill bill = billMapper.selectById(dto.getBillId());
        if (bill == null || !BillStatus.UNPAID.getCode().equals(bill.getStatus())) {
            throw new BusinessException("账单状态异常");
        }
        
        // 支付处理
        try {
            // 调用支付接口
            PaymentResult result = paymentService.process(dto);
            
            // 更新账单状态
            if (result.isSuccess()) {
                bill.setStatus(BillStatus.PAID.getCode());
                bill.setPaymentTime(LocalDateTime.now());
                billMapper.updateById(bill);
                
                // 发送支付成功通知
                sendPaymentSuccessNotification(bill);
            }
        } catch (Exception e) {
            log.error("支付处理失败", e);
            throw new BusinessException("支付失败");
        }
    }
}

三、停车场管理模块

3.1 功能设计

  • 车位信息管理
  • 车辆登记管理
  • 临时停车管理
  • 车位租赁管理
  • 车辆进出管理
  • 停车费用管理

3.2 数据库设计

-- 车位信息表
CREATE TABLE t_parking_space (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    space_no VARCHAR(20) COMMENT '车位编号',
    area_id BIGINT COMMENT '区域ID',
    type TINYINT COMMENT '类型:1-地上,2-地下',
    status TINYINT COMMENT '状态:0-空闲,1-已占用,2-已预约',
    owner_id BIGINT COMMENT '业主ID',
    create_time DATETIME
);

-- 车辆信息表
CREATE TABLE t_vehicle (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    plate_no VARCHAR(20) COMMENT '车牌号',
    resident_id BIGINT COMMENT '住户ID',
    vehicle_type TINYINT COMMENT '车辆类型:1-小型车,2-大型车',
    space_id BIGINT COMMENT '固定车位ID',
    status TINYINT COMMENT '状态:1-正常,0-禁用'
);

-- 停车记录表
CREATE TABLE t_parking_record (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    plate_no VARCHAR(20) COMMENT '车牌号',
    entry_time DATETIME COMMENT '进入时间',
    exit_time DATETIME COMMENT '离开时间',
    space_id BIGINT COMMENT '车位ID',
    fee_amount DECIMAL(10,2) COMMENT '费用',
    status TINYINT COMMENT '状态:1-在场,2-离场'
);

3.3 核心代码实现

@Service
public class ParkingServiceImpl implements ParkingService {
    
    @Autowired
    private ParkingSpaceMapper spaceMapper;
    @Autowired
    private ParkingRecordMapper recordMapper;
    
    @Override
    @Transactional
    public void vehicleEntry(VehicleEntryDTO dto) {
        // 验证车辆信息
        Vehicle vehicle = validateVehicle(dto.getPlateNo());
        
        // 查找可用车位
        ParkingSpace space = findAvailableSpace(dto.getAreaId());
        if (space == null) {
            throw new BusinessException("没有可用车位");
        }
        
        // 创建停车记录
        ParkingRecord record = new ParkingRecord();
        record.setPlateNo(dto.getPlateNo());
        record.setEntryTime(LocalDateTime.now());
        record.setSpaceId(space.getId());
        record.setStatus(ParkingStatus.IN.getCode());
        recordMapper.insert(record);
        
        // 更新车位状态
        space.setStatus(SpaceStatus.OCCUPIED.getCode());
        spaceMapper.updateById(space);
        
        // 发送入场通知
        sendEntryNotification(vehicle, space);
    }
    
    @Override
    @Transactional
    public PaymentDTO vehicleExit(String plateNo) {
        // 查询停车记录
        ParkingRecord record = recordMapper.selectLatestByPlateNo(plateNo);
        if (record == null || !ParkingStatus.IN.getCode().equals(record.getStatus())) {
            throw new BusinessException("未找到有效停车记录");
        }
        
        // 计算停车费用
        LocalDateTime exitTime = LocalDateTime.now();
        BigDecimal fee = calculateParkingFee(record.getEntryTime(), exitTime);
        
        // 更新记录
        record.setExitTime(exitTime);
        record.setFeeAmount(fee);
        record.setStatus(ParkingStatus.OUT.getCode());
        recordMapper.updateById(record);
        
        // 释放车位
        ParkingSpace space = spaceMapper.selectById(record.getSpaceId());
        space.setStatus(SpaceStatus.FREE.getCode());
        spaceMapper.updateById(space);
        
        // 返回支付信息
        return new PaymentDTO(record.getId(), fee);
    }
}

四、报修管理模块

4.1 功能设计

  • 报修工单提交
  • 维修人员派单
  • 维修进度跟踪
  • 维修评价
  • 报修统计分析
  • 常见问题处理

4.2 数据库设计

-- 报修工单表
CREATE TABLE t_repair_order (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    resident_id BIGINT COMMENT '报修人ID',
    type_id BIGINT COMMENT '报修类型ID',
    description TEXT COMMENT '问题描述',
    images VARCHAR(500) COMMENT '图片地址,多个逗号分隔',
    status TINYINT COMMENT '状态:0-待处理,1-已派单,2-处理中,3-已完成,4-已评价',
    create_time DATETIME,
    complete_time DATETIME COMMENT '完成时间'
);

-- 维修处理记录表
CREATE TABLE t_repair_process (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id BIGINT COMMENT '工单ID',
    worker_id BIGINT COMMENT '维修人员ID',
    process_desc TEXT COMMENT '处理说明',
    process_images VARCHAR(500) COMMENT '处理图片',
    create_time DATETIME
);

-- 维修评价表
CREATE TABLE t_repair_evaluation (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id BIGINT COMMENT '工单ID',
    score TINYINT COMMENT '评分:1-5星',
    content TEXT COMMENT '评价内容',
    create_time DATETIME
);

4.3 核心代码实现

@Service
@Transactional
public class RepairServiceImpl implements RepairService {
    
    @Autowired
    private RepairOrderMapper orderMapper;
    @Autowired
    private RepairProcessMapper processMapper;
    @Autowired
    private WorkerMapper workerMapper;
    
    @Override
    public void submitRepair(RepairDTO dto) {
        // 创建工单
        RepairOrder order = new RepairOrder();
        order.setResidentId(dto.getResidentId());
        order.setTypeId(dto.getTypeId());
        order.setDescription(dto.getDescription());
        order.setImages(String.join(",", dto.getImages()));
        order.setStatus(RepairStatus.PENDING.getCode());
        orderMapper.insert(order);
        
        // 自动分配维修人员
        Worker worker = assignWorker(dto.getTypeId());
        if (worker != null) {
            // 创建处理记录
            createProcessRecord(order.getId(), worker.getId());
            // 更新工单状态
            order.setStatus(RepairStatus.ASSIGNED.getCode());
            orderMapper.updateById(order);
            // 发送通知
            sendRepairNotification(order, worker);
        }
    }
    
    @Override
    public void processRepair(RepairProcessDTO dto) {
        // 查询工单
        RepairOrder order = orderMapper.selectById(dto.getOrderId());
        if (order == null) {
            throw new BusinessException("工单不存在");
        }
        
        // 记录处理过程
        RepairProcess process = new RepairProcess();
        process.setOrderId(dto.getOrderId());
        process.setWorkerId(dto.getWorkerId());
        process.setProcessDesc(dto.getProcessDesc());
        process.setProcessImages(String.join(",", dto.getImages()));
        processMapper.insert(process);
        
        // 更新工单状态
        if (dto.isCompleted()) {
            order.setStatus(RepairStatus.COMPLETED.getCode());
            order.setCompleteTime(LocalDateTime.now());
            orderMapper.updateById(order);
            
            // 发送完成通知
            sendCompletionNotification(order);
        }
    }
    
    @Override
    public void evaluateRepair(EvaluationDTO dto) {
        // 创建评价
        RepairEvaluation evaluation = new RepairEvaluation();
        evaluation.setOrderId(dto.getOrderId());
        evaluation.setScore(dto.getScore());
        evaluation.setContent(dto.getContent());
        evaluationMapper.insert(evaluation);
        
        // 更新工单状态
        RepairOrder order = orderMapper.selectById(dto.getOrderId());
        order.setStatus(RepairStatus.EVALUATED.getCode());
        orderMapper.updateById(order);
        
        // 更新维修人员评分
        updateWorkerScore(order.getWorkerId(), dto.getScore());
    }
    
    private Worker assignWorker(Long typeId) {
        // 根据维修类型和工作量分配维修人员
        List<Worker> availableWorkers = workerMapper.selectAvailableWorkers(typeId);
        if (availableWorkers.isEmpty()) {
            return null;
        }
        
        // 这里可以实现更复杂的分配算法,如考虑工作量、评分等因素
        return availableWorkers.get(0);
    }
}

这些模块的实现涉及到了许多实际业务场景,包括:

  1. 数据一致性处理
  2. 事务管理
  3. 异步通知
  4. 状态流转
  5. 业务规则校验
  6. 数据统计分析

在实际开发中,还需要注意:

  1. 接口的幂等性处理
  2. 并发控制
  3. 数据安全性
  4. 性能优化
  5. 日志记录
  6. 异常处理
  7. 测试用例编写

这些模块的代码实现仅供参考,实际项目中还需要根据具体需求进行调整和优化。

Java全栈项目 - 智能小区物业管理平台扩展模块详解

一、公告管理模块

1.1 功能设计

  • 公告发布管理
  • 公告类型管理
  • 公告审核流程
  • 公告阅读统计
  • 紧急公告推送
  • 公告模板管理

1.2 数据库设计

-- 公告信息表
CREATE TABLE t_announcement (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(100) NOT NULL COMMENT '公告标题',
    content TEXT COMMENT '公告内容',
    type_id BIGINT COMMENT '公告类型ID',
    priority TINYINT COMMENT '优先级:1-普通,2-重要,3-紧急',
    status TINYINT COMMENT '状态:0-待审核,1-已发布,2-已撤回',
    publisher_id BIGINT COMMENT '发布人ID',
    publish_time DATETIME COMMENT '发布时间',
    expire_time DATETIME COMMENT '过期时间',
    create_time DATETIME,
    update_time DATETIME
);

-- 公告阅读记录表
CREATE TABLE t_announcement_read (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    announcement_id BIGINT COMMENT '公告ID',
    reader_id BIGINT COMMENT '读者ID',
    read_time DATETIME COMMENT '阅读时间'
);

-- 公告类型表
CREATE TABLE t_announcement_type (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    type_name VARCHAR(50) COMMENT '类型名称',
    sort_order INT COMMENT '排序号',
    status TINYINT COMMENT '状态:0-禁用,1-启用'
);

1.3 核心代码实现

@Service
public class AnnouncementServiceImpl implements AnnouncementService {
    
    @Autowired
    private AnnouncementMapper announcementMapper;
    @Autowired
    private ReadRecordMapper readRecordMapper;
    @Autowired
    private MessageService messageService;
    
    @Override
    @Transactional
    public void publishAnnouncement(AnnouncementDTO dto) {
        // 创建公告
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(dto, announcement);
        announcement.setStatus(AnnouncementStatus.PENDING.getCode());
        announcementMapper.insert(announcement);
        
        // 如果是紧急公告,直接发布并推送
        if (PriorityLevel.URGENT.getCode().equals(dto.getPriority())) {
            announcement.setStatus(AnnouncementStatus.PUBLISHED.getCode());
            announcement.setPublishTime(LocalDateTime.now());
            announcementMapper.updateById(announcement);
            
            // 推送紧急通知
            sendUrgentNotification(announcement);
        } else {
            // 发起审核流程
            startApprovalProcess(announcement);
        }
    }
    
    @Override
    public PageResult<AnnouncementVO> queryAnnouncements(AnnouncementQuery query) {
        LambdaQueryWrapper<Announcement> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(query.getTypeId() != null, 
                  Announcement::getTypeId, query.getTypeId())
               .eq(query.getStatus() != null,
                   Announcement::getStatus, query.getStatus())
               .orderByDesc(Announcement::getCreateTime);
                   
        Page<Announcement> page = announcementMapper.selectPage(
            new Page<>(query.getPage(), query.getSize()),
            wrapper
        );
        
        return PageResult.of(page, this::convertToVO);
    }
    
    @Override
    public void recordReading(Long announcementId, Long readerId) {
        // 检查是否已读
        if (!hasRead(announcementId, readerId)) {
            ReadRecord record = new ReadRecord();
            record.setAnnouncementId(announcementId);
            record.setReaderId(readerId);
            record.setReadTime(LocalDateTime.now());
            readRecordMapper.insert(record);
        }
    }
    
    private void sendUrgentNotification(Announcement announcement) {
        // 获取所有需要通知的用户
        List<User> users = userMapper.selectAllValid();
        
        // 批量发送通知
        List<Message> messages = users.stream()
            .map(user -> createMessage(announcement, user))
            .collect(Collectors.toList());
        
        messageService.batchSend(messages);
    }
}

二、访客管理模块

2.1 功能设计

  • 访客预约登记
  • 访客通行码生成
  • 访客记录查询
  • 访客通行管理
  • 黑名单管理
  • 访客统计分析

2.2 数据库设计

-- 访客预约表
CREATE TABLE t_visitor_appointment (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    visitor_name VARCHAR(50) COMMENT '访客姓名',
    visitor_phone VARCHAR(20) COMMENT '访客电话',
    id_card VARCHAR(18) COMMENT '身份证号',
    resident_id BIGINT COMMENT '被访人ID',
    visit_time DATETIME COMMENT '预约访问时间',
    leave_time DATETIME COMMENT '预计离开时间',
    reason VARCHAR(200) COMMENT '来访事由',
    status TINYINT COMMENT '状态:0-待审核,1-已通过,2-已拒绝',
    create_time DATETIME
);

-- 访客通行记录表
CREATE TABLE t_visitor_access (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    appointment_id BIGINT COMMENT '预约ID',
    access_code VARCHAR(20) COMMENT '通行码',
    entry_time DATETIME COMMENT '实际进入时间',
    exit_time DATETIME COMMENT '实际离开时间',
    status TINYINT COMMENT '状态:1-已进入,2-已离开'
);

-- 访客黑名单表
CREATE TABLE t_visitor_blacklist (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    visitor_name VARCHAR(50) COMMENT '访客姓名',
    id_card VARCHAR(18) COMMENT '身份证号',
    reason VARCHAR(200) COMMENT '拉黑原因',
    operator_id BIGINT COMMENT '操作人ID',
    create_time DATETIME
);

2.3 核心代码实现

@Service
public class VisitorServiceImpl implements VisitorService {
    
    @Autowired
    private VisitorAppointmentMapper appointmentMapper;
    @Autowired
    private VisitorAccessMapper accessMapper;
    @Autowired
    private BlacklistMapper blacklistMapper;
    
    @Override
    @Transactional
    public String createAppointment(VisitorAppointmentDTO dto) {
        // 检查访客是否在黑名单中
        if (isInBlacklist(dto.getIdCard())) {
            throw new BusinessException("该访客已被列入黑名单");
        }
        
        // 创建预约记录
        VisitorAppointment appointment = new VisitorAppointment();
        BeanUtils.copyProperties(dto, appointment);
        appointment.setStatus(AppointmentStatus.PENDING.getCode());
        appointmentMapper.insert(appointment);
        
        // 生成通行码
        String accessCode = generateAccessCode();
        
        // 创建通行记录
        VisitorAccess access = new VisitorAccess();
        access.setAppointmentId(appointment.getId());
        access.setAccessCode(accessCode);
        accessMapper.insert(access);
        
        // 发送通知给被访人
        sendAppointmentNotification(appointment);
        
        return accessCode;
    }
    
    @Override
    public void recordEntry(String accessCode) {
        VisitorAccess access = accessMapper.selectByCode(accessCode);
        if (access == null) {
            throw new BusinessException("无效的通行码");
        }
        
        // 验证预约状态
        VisitorAppointment appointment = appointmentMapper.selectById(
            access.getAppointmentId());
        if (!AppointmentStatus.APPROVED.getCode().equals(appointment.getStatus())) {
            throw new BusinessException("预约未审核通过");
        }
        
        // 记录进入时间
        access.setEntryTime(LocalDateTime.now());
        access.setStatus(AccessStatus.ENTERED.getCode());
        accessMapper.updateById(access);
        
        // 发送通知给被访人
        sendEntryNotification(appointment);
    }
    
    @Override
    public void recordExit(String accessCode) {
        VisitorAccess access = accessMapper.selectByCode(accessCode);
        if (access == null) {
            throw new BusinessException("无效的通行码");
        }
        
        // 记录离开时间
        access.setExitTime(LocalDateTime.now());
        access.setStatus(AccessStatus.EXITED.getCode());
        accessMapper.updateById(access);
    }
    
    private String generateAccessCode() {
        // 生成唯一的6位数字通行码
        return String.format("%06d", new Random().nextInt(1000000));
    }
    
    private boolean isInBlacklist(String idCard) {
        return blacklistMapper.countByIdCard(idCard) > 0;
    }
}

三、投诉建议模块

3.1 功能设计

  • 投诉建议提交
  • 处理流程管理
  • 满意度评价
  • 投诉分类管理
  • 处理时效监控
  • 统计分析报表

3.2 数据库设计

-- 投诉建议表
CREATE TABLE t_complaint (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    resident_id BIGINT COMMENT '投诉人ID',
    type_id BIGINT COMMENT '投诉类型ID',
    title VARCHAR(100) COMMENT '标题',
    content TEXT COMMENT '内容',
    images VARCHAR(500) COMMENT '图片证据',
    status TINYINT COMMENT '状态:0-待处理,1-处理中,2-已处理,3-已评价',
    priority TINYINT COMMENT '优先级:1-普通,2-重要,3-紧急',
    create_time DATETIME,
    deadline DATETIME COMMENT '处理截止时间'
);

-- 投诉处理记录表
CREATE TABLE t_complaint_process (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    complaint_id BIGINT COMMENT '投诉ID',
    handler_id BIGINT COMMENT '处理人ID',
    process_desc TEXT COMMENT '处理说明',
    process_time DATETIME COMMENT '处理时间'
);

-- 投诉评价表
CREATE TABLE t_complaint_evaluation (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    complaint_id BIGINT COMMENT '投诉ID',
    satisfaction_level TINYINT COMMENT '满意度:1-5星',
    comment TEXT COMMENT '评价内容',
    create_time DATETIME
);

3.3 核心代码实现

@Service
public class ComplaintServiceImpl implements ComplaintService {
    
    @Autowired
    private ComplaintMapper complaintMapper;
    @Autowired
    private ProcessMapper processMapper;
    @Autowired
    private EvaluationMapper evaluationMapper;
    
    @Override
    @Transactional
    public void submitComplaint(ComplaintDTO dto) {
        // 创建投诉记录
        Complaint complaint = new Complaint();
        BeanUtils.copyProperties(dto, complaint);
        complaint.setStatus(ComplaintStatus.PENDING.getCode());
        
        // 设置处理截止时间
        complaint.setDeadline(calculateDeadline(dto.getPriority()));
        complaintMapper.insert(complaint);
        
        // 分配处理人员
        Handler handler = assignHandler(dto.getTypeId());
        if (handler != null) {
            // 创建处理记录
            createProcessRecord(complaint.getId(), handler.getId());
            
            // 发送处理通知
            sendProcessNotification(complaint, handler);
        }
    }
    
    @Override
    public void processComplaint(ProcessDTO dto) {
        // 更新投诉状态
        Complaint complaint = complaintMapper.selectById(dto.getComplaintId());
        complaint.setStatus(ComplaintStatus.PROCESSING.getCode());
        complaintMapper.updateById(complaint);
        
        // 记录处理过程
        ComplaintProcess process = new ComplaintProcess();
        process.setComplaintId(dto.getComplaintId());
        process.setHandlerId(dto.getHandlerId());
        process.setProcessDesc(dto.getProcessDesc());
        process.setProcessTime(LocalDateTime.now());
        processMapper.insert(process);
        
        // 如果处理完成
        if (dto.isCompleted()) {
            complaint.setStatus(ComplaintStatus.PROCESSED.getCode());
            complaintMapper.updateById(complaint);
            
            // 发送评价提醒
            sendEvaluationReminder(complaint);
        }
    }
    
    @Override
    public void evaluateComplaint(EvaluationDTO dto) {
        // 创建评价记录
        ComplaintEvaluation evaluation = new ComplaintEvaluation();
        evaluation.setComplaintId(dto.getComplaintId());
        evaluation.setSatisfactionLevel(dto.getSatisfactionLevel());
        evaluation.setComment(dto.getComment());
        evaluationMapper.insert(evaluation);
        
        // 更新投诉状态
        Complaint complaint = complaintMapper.selectById(dto.getComplaintId());
        complaint.setStatus(ComplaintStatus.EVALUATED.getCode());
        complaintMapper.updateById(complaint);
        
        // 更新处理人员的评分
        updateHandlerRating(complaint.getHandlerId(), dto.getSatisfactionLevel());
    }
    
    private LocalDateTime calculateDeadline(Integer priority) {
        // 根据优先级计算处理截止时间
        int hours = switch (priority) {
            case 3 -> 4;  // 紧急
            case 2 -> 24; // 重要
            default -> 48;// 普通
        };
        return LocalDateTime.now().plusHours(hours);
    }
}

四、统计分析模块

4.1 功能设计

  • 物业费用统计
  • 报修分析
  • 投诉分析
  • 访客统计
  • 车位使用分析
  • 数据可视化展示

4.2 数据库设计

-- 统计数据表
CREATE TABLE t_statistics_daily (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    stat_date DATE COMMENT '统计日期',
    stat_type VARCHAR(50) COMMENT '统计类型',
    stat_value DECIMAL(10,2) COMMENT '统计值',
    create_time DATETIME
);

-- 统计维度表
CREATE TABLE t_statistics_dimension (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    dimension_key VARCHAR(50) COMMENT '维度键',
    dimension_value VARCHAR(50) COMMENT '维度值',
    parent_id BIGINT COMMENT '父维度ID'
);

4.3 核心代码实现

@Service
public class StatisticsServiceImpl implements StatisticsService {
    
    @Autowired
    private StatisticsMapper statisticsMapper;
    @Autowired
    private PropertyFeeMapper feeMapper;
    @Autowired
    private RepairMapper repairMapper;
    @Autowired
    private ComplaintMapper complaintMapper;
    
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    public void generateDailyStatistics() {
        LocalDate yesterday = LocalDate.now().minusDays(1);
        
        // 统计物业费收入
        BigDecimal feeIncome = calculateFeeIncome(yesterday);
        saveStatistics(yesterday, "FEE_INCOME", feeIncome);
        
        // 统计报修数据
        Map<String, Integer> repairStats = calculateRepairStatistics(yesterday);
        repairStats.forEach((type, count) -> 
            saveStatistics(yesterday, "REPAIR_" + type, new BigDecimal(count)));
        
        // 统计投诉数据
        Map<String, Integer> complaintStats = calculateComplaintStatistics(yesterday);
        complaintStats.forEach((type, count) -> 
            saveStatistics(yesterday, "COMPLAINT_" + type, new BigDecimal(count)));
    }
    
    @Override
    public StatisticsVO getPropertyFeeAnalysis(StatisticsQuery query) {
        StatisticsVO vo = new StatisticsVO();
        
        // 收费率统计
        vo.setCollectionRate(calculateCollectionRate(query.getStartDate(), 
                                                   query.getEndDate()));
        
        // 收入趋势
        vo.setIncomeTrend(getIncomeTrend(query.getStartDate(), 
                                        query.getEndDate()));
        
        // 费用类型分布
        vo.setFeeTypeDistribution(getFeeTypeDistribution(query.getStartDate(), 
                                                       query.getEndDate()));
        
        return vo;
    }
    
    @Override
    public StatisticsVO getRepairAnalysis(StatisticsQuery query) {
        StatisticsVO vo = new StatisticsVO();
        
        // 报修类型分布
        vo.setRepairTypeDistribution(getRepairTypeDistribution(query.getStartDate(), 
                                                             query.getEndDate()));
        
        // 处理时效分析
        vo.setProcessingEfficiency(calculateProcessingEfficiency(query.getStartDate(), 
                                                               query.getEndDate()));
        
        // 满意度分析
        vo.setSatisfactionAnalysis(calculateSatisfactionRate(query.getStartDate(), 
                                                           query.getEndDate()));
        
        return vo;
    }
    
    private void saveStatistics(LocalDate date, String type, BigDecimal value) {
        Statistics stat = new Statistics();
        stat.setStatDate(date);
        stat.setStatType(type);
        stat.setStatValue(value);
        statisticsMapper.insert(stat);
    }
    
    private BigDecimal calculateCollectionRate(LocalDate startDate, LocalDate endDate) {
        // 查询总应收金额
        BigDecimal totalAmount = feeMapper.sumTotalAmount(startDate, endDate);
        
        // 查询实收金额
        BigDecimal collectedAmount = feeMapper.sumCollectedAmount(startDate, endDate);
        
        // 计算收费率
        return totalAmount.compareTo(BigDecimal.ZERO) == 0 ? 
            BigDecimal.ZERO : 
            collectedAmount.divide(totalAmount, 4, RoundingMode.HALF_UP)
                         .multiply(new BigDecimal("100"));
    }
    
    private List<ChartData> getIncomeTrend(LocalDate startDate, LocalDate endDate) {
        return statisticsMapper.selectIncomeTrend(startDate, endDate)
            .stream()
            .map(this::convertToChartData)
            .collect(Collectors.toList());
    }
}

4.4 数据可视化实现

<!-- StatisticsChart.vue -->
<template>
  <div class="statistics-chart">
    <el-row :gutter="20">
      <!-- 收费率卡片 -->
      <el-col :span="6">
        <el-card class="stat-card">
          <div class="stat-title">物业费收费率</div>
          <div class="stat-value">{{ collectionRate }}%</div>
          <div class="stat-chart">
            <v-chart :option="getGaugeOption(collectionRate)" />
          </div>
        </el-card>
      </el-col>
      
      <!-- 收入趋势图 -->
      <el-col :span="12">
        <el-card class="stat-card">
          <div class="stat-title">收入趋势</div>
          <div class="stat-chart">
            <v-chart :option="getLineOption(incomeTrend)" />
          </div>
        </el-card>
      </el-col>
      
      <!-- 费用类型分布 -->
      <el-col :span="6">
        <el-card class="stat-card">
          <div class="stat-title">费用类型分布</div>
          <div class="stat-chart">
            <v-chart :option="getPieOption(feeTypeDistribution)" />
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart, LineChart, GaugeChart } from 'echarts/charts'
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'

use([
  CanvasRenderer,
  PieChart,
  LineChart,
  GaugeChart,
  GridComponent,
  TooltipComponent,
  LegendComponent
])

export default {
  name: 'StatisticsChart',
  
  props: {
    collectionRate: {
      type: Number,
      default: 0
    },
    incomeTrend: {
      type: Array,
      default: () => []
    },
    feeTypeDistribution: {
      type: Array,
      default: () => []
    }
  },
  
  methods: {
    getGaugeOption(value) {
      return {
        series: [{
          type: 'gauge',
          startAngle: 180,
          endAngle: 0,
          min: 0,
          max: 100,
          splitNumber: 10,
          itemStyle: {
            color: '#58D9F9'
          },
          progress: {
            show: true,
            width: 30
          },
          pointer: {
            show: false
          },
          axisLine: {
            lineStyle: {
              width: 30
            }
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: false
          },
          axisLabel: {
            show: false
          },
          detail: {
            valueAnimation: true,
            formatter: '{value}%',
            fontSize: 20
          },
          data: [{
            value: value
          }]
        }]
      }
    },
    
    getLineOption(data) {
      return {
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          type: 'category',
          data: data.map(item => item.date)
        },
        yAxis: {
          type: 'value'
        },
        series: [{
          data: data.map(item => item.value),
          type: 'line',
          smooth: true,
          areaStyle: {}
        }]
      }
    },
    
    getPieOption(data) {
      return {
        tooltip: {
          trigger: 'item'
        },
        legend: {
          orient: 'vertical',
          left: 'left'
        },
        series: [{
          type: 'pie',
          radius: '50%',
          data: data,
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
          }
        }]
      }
    }
  }
}
</script>

<style scoped>
.statistics-chart {
  padding: 20px;
}

.stat-card {
  height: 350px;
}

.stat-title {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 15px;
}

.stat-value {
  font-size: 24px;
  color: #409EFF;
  text-align: center;
  margin: 10px 0;
}

.stat-chart {
  height: 250px;
}
</style>

这些模块的实现要点:

  1. 数据安全性

    • 敏感信息加密
    • 访问权限控制
    • 操作日志记录
  2. 性能优化

    • 合理使用缓存
    • SQL优化
    • 大数据量分页处理
  3. 业务规则

    • 状态流转控制
    • 数据验证
    • 业务限制条件
  4. 通知机制

    • 消息推送
    • 邮件通知
    • 短信提醒
  5. 统计分析

    • 数据聚合
    • 多维度分析
    • 可视化展示
  6. 系统集成

    • 第三方支付
    • 短信服务
    • 对接硬件设备

这些模块的具体实现还需要根据实际业务需求进行调整和扩展。


http://www.kler.cn/a/442019.html

相关文章:

  • 【设计模式】 单例模式(单例模式哪几种实现,如何保证线程安全,反射破坏单例模式)
  • 【Linux系统编程】—— 深度解析进程等待与终止:系统高效运行的关键
  • 【Cadence tip】噪声仿真方法
  • 用户中心项目教程(四)---Vue脚手架完成前端初始化
  • Linux 操作二:文件映射与文件状态
  • 构建安全防线:基于视频AI的煤矿管理系统架构创新成果展示
  • 新知DAC维修,换牛,
  • Rust操作符和符号全解析
  • Java对集合的操作方法
  • 面试小札:闪电五连鞭_7
  • opencv # Sobel算子、Laplacian算子、Canny边缘检测、findContours、drawContours绘制轮廓、外接矩形
  • Sentry日志管理thinkphp8 tp8 sentry9 sentry8 php8.x配置步骤, tp8自定义异常处理类使用方法
  • NSDT 3DConvert:高效实现大模型文件在线预览与转换
  • 关于llama2:从原始llama-2-7b到llama-2-7b-hf的权重转换教程
  • cesium 与 threejs 对比
  • attack xv6
  • Pytorch | 从零构建ResNet对CIFAR10进行分类
  • RabbitMQ:添加virtualHost
  • 005 QT常用控件Qwidget_上
  • 随手记:小程序兼容后台的wangEditor富文本配置链接
  • VMware ubuntu16.04怎么设置静态IP联网
  • openharmony bootanimation分析及常见错误
  • 如何在 Debian 上安装 Dovecot(POP / IMAP)?
  • TCP客户端模拟链接websocket服务端
  • 基于ubuntu的mysql 8.0安装教程
  • 中国当代篆刻孙溟㠭作品《美》