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 性能优化
- 使用 Redis 缓存热点数据
@Cacheable(value = "resident", key = "#id")
public ResidentVO getResidentInfo(Long id) {
Resident resident = residentMapper.selectById(id);
return convertToVO(resident);
}
-
使用 MyBatis-Plus 分页插件优化查询
-
实现数据库读写分离
4.2 安全优化
- 实现基于 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);
}
}
- 数据加密传输
- 防SQL注入
- XSS防护
五、项目部署
5.1 环境配置
- JDK 1.8+
- Maven 3.6+
- MySQL 8.0
- Redis 6.x
- Nginx 1.18
5.2 部署架构
- 采用前后端分离部署
- 使用 Docker 容器化部署
- 实现服务高可用
六、项目总结
6.1 技术亮点
- 采用主流的 Java 全栈技术栈
- 实现了完整的物业管理业务流程
- 良好的系统性能和安全性
- 支持高并发和分布式部署
6.2 未来展望
- 引入微服务架构
- 集成物联网设备
- 开发移动端应用
- 引入人工智能技术
通过本项目的开发实践,不仅实现了物业管理的信息化和智能化,也积累了丰富的全栈开发经验。
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);
}
}
这些模块的实现涉及到了许多实际业务场景,包括:
- 数据一致性处理
- 事务管理
- 异步通知
- 状态流转
- 业务规则校验
- 数据统计分析
在实际开发中,还需要注意:
- 接口的幂等性处理
- 并发控制
- 数据安全性
- 性能优化
- 日志记录
- 异常处理
- 测试用例编写
这些模块的代码实现仅供参考,实际项目中还需要根据具体需求进行调整和优化。
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>
这些模块的实现要点:
-
数据安全性
- 敏感信息加密
- 访问权限控制
- 操作日志记录
-
性能优化
- 合理使用缓存
- SQL优化
- 大数据量分页处理
-
业务规则
- 状态流转控制
- 数据验证
- 业务限制条件
-
通知机制
- 消息推送
- 邮件通知
- 短信提醒
-
统计分析
- 数据聚合
- 多维度分析
- 可视化展示
-
系统集成
- 第三方支付
- 短信服务
- 对接硬件设备
这些模块的具体实现还需要根据实际业务需求进行调整和扩展。