作为一名长期从事Web开发的技术人员,我最近完成了一个基于Vue.js的小区水电费收费系统开发项目。这个系统旨在解决传统小区水电费管理中的诸多痛点:手工抄表效率低下、缴费流程繁琐、数据统计困难等问题。通过前后端分离的架构设计,我们实现了从抄表、计费到缴费的全流程数字化管理。
系统采用Vue3+Element Plus构建前端界面,Spring Boot提供后端服务,MySQL作为数据库存储。在开发过程中,我们特别注重用户体验和系统性能优化,使得最终产品不仅功能完善,而且操作流畅。下面我将从技术实现角度详细解析这个项目的开发过程。
前端框架选择Vue3而非Vue2,主要基于以下考虑:
我们使用的主要技术栈包括:
javascript复制// 典型的前端项目结构
src/
├── api/ # API请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
├── composables/ # 组合式函数
├── router/ # 路由配置
├── stores/ # Pinia状态管理
├── styles/ # 全局样式
├── utils/ # 工具函数
└── views/ # 页面组件
后端采用Spring Boot框架,主要考虑其快速开发特性和丰富的生态系统。我们设计了清晰的层级结构:
数据库设计遵循第三范式,主要包含以下表:
系统采用RBAC(基于角色的访问控制)模型,定义了三种角色:
权限控制通过后端接口权限注解和前端路由守卫双重保障:
java复制// 后端权限控制示例
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/meters")
public ResponseEntity<?> createMeter(@RequestBody MeterDTO meterDTO) {
// 创建水电表逻辑
}
javascript复制// 前端路由守卫
router.beforeEach((to, from, next) => {
const userStore = useUserStore()
if (to.meta.requiresAuth && !userStore.isAuthenticated) {
next('/login')
} else if (to.meta.roles && !to.meta.roles.includes(userStore.role)) {
next('/403') // 无权限页面
} else {
next()
}
})
水电费计算是本系统的核心功能,我们实现了以下特性:
java复制public class BillCalculator {
private static final Map<String, List<Tier>> PRICE_TIERS = Map.of(
"water", List.of(new Tier(0, 10, 3.5), new Tier(10, 20, 4.2)),
"electricity", List.of(new Tier(0, 100, 0.6), new Tier(100, 400, 0.8))
);
public BigDecimal calculateUsageCharge(String utilityType, BigDecimal usage) {
List<Tier> tiers = PRICE_TIERS.get(utilityType);
BigDecimal total = BigDecimal.ZERO;
for (Tier tier : tiers) {
if (usage.compareTo(BigDecimal.ZERO) <= 0) break;
BigDecimal tierUsage = usage.min(tier.max.subtract(tier.min));
if (tierUsage.compareTo(BigDecimal.ZERO) > 0) {
total = total.add(tierUsage.multiply(tier.price));
usage = usage.subtract(tierUsage);
}
}
return total.setScale(2, RoundingMode.HALF_UP);
}
private static class Tier {
BigDecimal min;
BigDecimal max;
BigDecimal price;
Tier(int min, int max, double price) {
this.min = new BigDecimal(min);
this.max = new BigDecimal(max);
this.price = new BigDecimal(price);
}
}
}
初期实现中,批量导入1000条抄表记录需要近10秒,经过以下优化后降至1秒内:
java复制@Transactional
public void batchImportMeterReadings(List<MeterReadingDTO> readings) {
// 分批处理,每批500条
Lists.partition(readings, 500).forEach(batch -> {
// 使用MyBatis批量插入
meterReadingMapper.batchInsert(batch);
// 异步生成账单
CompletableFuture.runAsync(() ->
generateBillsForReadings(batch), taskExecutor);
});
}
为确保缴费数据准确,我们实现了以下机制:
mermaid复制stateDiagram-v2
[*] --> UNPAID
UNPAID --> PAID: 支付成功
UNPAID --> PARTIAL_PAID: 部分支付
UNPAID --> CANCELLED: 账单作废
PARTIAL_PAID --> PAID: 继续支付
PARTIAL_PAID --> CANCELLED: 账单作废
PAID --> [*]
CANCELLED --> [*]
推荐使用以下开发环境:
前端开发环境配置:
bash复制# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 构建生产版本
npm run build
我们采用Docker容器化部署,docker-compose.yml配置如下:
yaml复制version: '3.8'
services:
frontend:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./dist:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- backend
backend:
build: ./backend
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=jdbc:mysql://db:3306/utility_billing
- DB_USER=admin
- DB_PASSWORD=secret
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=utility_billing
- MYSQL_USER=admin
- MYSQL_PASSWORD=secret
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
volumes:
mysql_data:
在开发这个小区水电费收费系统的过程中,我积累了以下几点重要经验:
领域模型设计:初期对水电费业务的理解不够深入,导致第一次设计的数据库模型存在冗余。后来通过与物业管理人员深入交流,重构了数据模型,特别是水电表与房产的关联关系。
性能优化:批量抄表功能最初性能很差,通过引入分批处理、异步计算和数据库优化,最终实现了10倍的性能提升。
安全性考虑:系统最初缺乏完善的权限控制,后来增加了细粒度的操作日志和敏感操作二次验证,大大提高了系统安全性。
用户体验:通过多次与最终用户(物业人员和住户)的可用性测试,不断优化操作流程,特别是简化了缴费和账单查询的步骤。
这个项目让我深刻体会到,一个好的管理系统不仅要技术实现正确,更要深入理解业务需求,站在最终用户的角度思考问题。未来如果继续开发,我计划增加以下功能:
整个项目的开发过程让我对Vue3和Spring Boot的配合使用有了更深的理解,特别是在状态管理和API设计方面积累了宝贵经验。希望这个案例能为类似的小区管理系统开发提供参考。