news 2026/10/8 10:13:47

SpringBoot电力营销系统毕设全攻略:从业务建模到部署演示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot电力营销系统毕设全攻略:从业务建模到部署演示

1. 项目概述与业务需求拆解

如果你最近正在翻计算机毕设选题列表,十有八九会撞见这个题目:基于 SpringBoot 的电力营销系统。后面通常还跟着一串关键词:Java、SpringBoot、电力营销管理平台、全流程管理系统。我的建议是,这个题不但能选,而且是个越做越有内容的题。它不是那种表面花哨、实际只有增删改查的空壳,也不像个别冷门方向那样做完了答辩老师都提不出问题、甚至看不懂你在做什么。电力营销系统最大的优势在于:业务逻辑真实、数据链路完整、技术选型贴合企业主流,论文好写、系统好讲,演示的时候也拿得出手。

这个系统本质上要解决什么问题?咱们用大白话说:电力公司要给用户建档立户,记录每个月用了多少电,按电价算出电费,把账单发出去、把钱收回来,如果没交清还得记一笔欠费台账,最后再把这一堆数据汇总成报表。这整条流程——从客户档案、计量管理、抄表录入、电费计算,到账单生成、缴费核销、账务统计——就是一个完整的电力营销业务闭环。你作为开发者的任务,就是用 Java 和 SpringBoot 把这套流程从线下搬到线上,让管理员能维护用户档案,抄表员能批量录入电表读数,系统自动算费,财务确认到账,领导能看统计报表。

有人可能会问:这不就是个普通的业务管理系统吗?和图书管理、商品管理有什么区别?区别大了。商品管理系统通常只有一套简单的库存和订单流转,而电力营销系统天然带着阶梯电价、按需计费、欠费催缴、账实核对这些特殊逻辑。举个例子,一个居民用户一个月用了 300 度电,和用了 600 度电,单价不是一乘了事,而是套用电价规则,超出阶梯的部分按更高的价格计算。这类业务规则一旦在代码里落地,项目深度立刻不一样。

适合谁来参考?如果你是计算机专业本科生、正在为毕设发愁,或者你是研究生、想在这个方向上加一点算法或大数据分析做创新点,这篇内容都能给你一条完整的实施路径。我还见过一些自学 Java 想做个像样项目放进简历的伙伴,也适合按这个方向练手。它覆盖了工程搭建、权限安全、复杂查询、报表聚合、前后端联调这些日常工作中最常用的技能,学完不是只有毕业那一下有用,面试聊项目的时候也很有料。

2. 总体架构与工程结构设计

2.1 单体架构就够了,别给自己找事

先说一个很多同学容易踩的坑:看着网上那些分布式电商项目用 Nacos、Gateway、OpenFeign,就也想把自己的毕设拆成微服务架构。我的意见很直接:电力营销系统,单体应用完全够用,甚至更合适。毕设评审看重的是业务流程是否完整、核心逻辑是否合理、代码质量是否规范,而不是你拆了几个服务。你要真把 Spring Cloud 全家桶塞进来,且不说部署到答辩演示环境有多麻烦,单是一个本地服务注册发现调试,就足够让你在最后一周崩溃两回。

单体 SpringBoot 工程配合模块化包结构,已经能把客户的思路表达得很清楚。控制层只做参数接收和结果返回,业务层专注事务和规则计算,数据层用 MyBatis-Plus 操作数据库,前端要么用 Vue 做前后端分离,要么用 Thymeleaf 做传统的服务端渲染。我通常建议毕设选前后端分离,因为后面简历上能写"独立完成前后端全栈开发",而且 Vue 的界面效果比 JSP 时代好看太多,答辩演示的视觉分很重要。

2.2 后端工程结构怎么组织才显得专业

有些同学的项目结构是 controller 一层下面全是揉在一起的 service 类,一个类几千行,答辩老师一打开就皱眉头。这里我给你一个可以直接套用的结构模板:

power-marketing/ ├── src/main/java/com/example/powermarketing/ │ ├── PowerMarketingApplication.java │ ├── config/ # 配置类:跨域、MyBatis-Plus分页、拦截器注册 │ ├── common/ # 统一返回结果、异常处理、常量定义 │ │ ├── Result.java │ │ ├── ResultCode.java │ │ ├── BusinessException.java │ │ └── GlobalExceptionHandler.java │ ├── entity/ # 数据库实体 │ │ ├── User.java │ │ ├── Customer.java │ │ ├── MeterPoint.java │ │ ├── MeterReading.java │ │ └── ElectricityBill.java │ ├── mapper/ # MyBatis-Plus 的 Mapper 接口 │ ├── service/ # 业务接口 │ │ ├── CustomerService.java │ │ ├── MeterReadingService.java │ │ └── impl/ # 业务实现类 │ ├── controller/ # REST 接口 │ │ ├── AuthController.java │ │ ├── CustomerController.java │ │ └── BillController.java │ └── util/ # 工具类:JWT工具、日期工具、电价计算器 └── src/main/resources/ ├── application.yml └── mapper/ # 自定义 XML SQL(复杂报表查询放这里)

每个实体和对应的 Controller 一一对应,Service 接口和 Impl 分离,这虽然不是必须的,但答辩老师看到这种结构时,第一印象就是"这学生是认真练过的"。统一返回结果Result尤其重要,我见过很多同学接口返回各种乱七八糟的 Map 或者裸 JSON,前端解析时一头雾水,统一成{ code, message, data }之后,所有接口风格一致,联调效率高很多。

2.3 数据库设计是电力营销系统的灵魂

说实话,这个项目的很多代码是在数据库表设计完成的那一刻就定了大半。表没设计好,后面写一万行代码都是在补窟窿。我按业务模块给你列一下核心表:

权限模块

  • sys_user:用户表,字段包含 id、username、password(BCrypt 加密存储)、real_name、role_id、status。不要分什么管理员表、抄表员表,统一放一张用户表,用角色区分。
  • sys_role:角色表,预置超级管理员、抄表员、财务员、普通管理员几种角色。
  • sys_menu / sys_role_menu:菜单权限表。如果毕设时间紧,可以简化成角色字段直接判断权限,不做细粒度菜单管理,但这么写论文的时候"权限设计"一章会显得单薄,所以建议做一套简化版 RBAC。

档案与业务模块

  • customer:客户档案表,这是整个系统的主数据。包含用户编号、姓名、身份证号(脱敏展示)、联系电话、用电地址、供电单位、户表关系、建档日期。
  • meter_point:计量点表,一个客户可以有一个或多个计量点,比如一个商铺装了总表和分表。字段有计量点编号、所属用户、电表型号、倍率、安装日期、状态。
  • meter_reading:抄表记录表,记录某个月某个计量点抄得的电表示数、抄表日期、抄表人、数据来源。这里有一条经验:录的是表计示数,而不是电量,电量是算出来存到账单里的,这样能保证原始抄表数据可追溯。
  • tariff:电价表,用来配置不同用电类别(居民、一般工商业、农业)的目录电价和阶梯阈值。
  • electricity_bill:电费账单表,每月的计费结果。字段要有账单月份、用户编号、计量点编号、抄表示数、倍率、电量、电费金额、优惠金额、应收金额、实收金额、缴费状态、生成时间。
  • payment_record:缴费记录表,每一笔缴费流水。

统计与日志

  • operation_log:操作日志表,记录谁在什么时间干了什么,毕设里做审计线索很好用。
  • reconcile_statistics:这个可以不建表,用 SQL 联表聚合出一张月度汇总也可以,答辩讲清楚你的统计口径就行。

我把核心表关系说清楚:用户和角色是多对一,客户和计量点是一对多,计量点和抄表记录是一对多,月度抄表记录通过计算生成电费账单,账单和缴费记录是一对多。建议在建表之前,先用 PowerDesigner 或者 Navicat 的模型绘制功能画一张 ER 图,这张图直接可以贴进毕业论文,开题报告里还能放缩小版,一份设计图多个地方用,很划算。

3. 核心功能模块与实现细节

3.1 登录认证与权限拦截:JWT + Spring 拦截器

电力营销系统涉及电费、用户档案这些敏感业务,登录认证这块不能糊弄。我推荐用 JWT 做无状态认证,好处是可以和 Vue 前端完美配合,token存在浏览器本地存储中,每次请求在请求头带上,后端用拦截器统一校验。

先看看配置文件里怎么注册拦截器:

@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Resource private AuthInterceptor authInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns("/**") .excludePathPatterns( "/auth/login", "/auth/register", "/error", "/doc.html", "/webjars/**", "/favicon.ico" ); } }

登录接口生成 token 的代码也比较固定:

@Service public class AuthServiceImpl implements AuthService { @Resource private SysUserMapper sysUserMapper; @Resource private JwtUtil jwtUtil; @Override public String login(LoginRequest request) { LambdaQueryWrapper<SysUser> wrapper = Wrappers.lambdaQuery(); wrapper.eq(SysUser::getUsername, request.getUsername()); SysUser user = sysUserMapper.selectOne(wrapper); if (user == null) { throw new BusinessException("用户名或密码错误"); } if (!BCrypt.checkpw(request.getPassword(), user.getPassword())) { throw new BusinessException("用户名或密码错误"); } if (user.getStatus() != 1) { throw new BusinessException("账号已被禁用"); } // 生成 token,userId 和 roleId 放进载荷 return jwtUtil.generateToken(user.getId(), user.getRoleId()); } }

这里有个细节:登录失败提示统一写成"用户名或密码错误",不要分别提示"用户不存在""密码错误",防账号探测属于安全常识,答辩老师问起来你能说出这个理由,印象分会不一样。另外密码必须用 BCrypt 加密,千万不要 MD5 或者明文存,我在面试中见过太多在校生项目密码直接明文存数据库,这是一个非常扎眼的低级失误。

权限控制方面,我在拦截器里拿到用户角色后,可以简单粗暴地做角色匹配:

@Component public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getMethod().equals("OPTIONS")) { return true; // 放行预检请求,避免跨域问题 } String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); } if (token == null || token.isEmpty()) { throw new BusinessException(401, "未登录或登录已过期"); } // 校验 token 并解析出 userId、roleId 放入 request attribute Claims claims = jwtUtil.parseToken(token); if (claims == null) { throw new BusinessException(401, "token 无效"); } request.setAttribute("userId", claims.get("userId")); request.setAttribute("roleId", claims.get("roleId")); return true; } }

如果你想做到按角色区分接口访问,就在拦截器里维护一个"接口路径-允许角色"的映射表,或者用@RequireRole注解加在 Controller 方法上,配合切面做校验。能把这层做了,论文里可以专门写一节"基于 RBAC 的权限控制设计",答辩就能讲一段。

3.2 抄表计算模块:为什么存示数而不是直接存电量

抄表流程是电力营销的核心数据源。抄表员在系统里选择客户的计量点,填入本次电表示数,系统自动计算本次用电量。听起来简单,但实际上有大学问。

我之前说过,数据库里应当保存的是表计示数(电表上拍的读数),而不是用电量。这背后的原因一言以蔽之:示数是原始凭证,电量是派生物。如果存的是电量,一旦电价政策调整或者要核对某个月的明细,你没有任何办法回溯验证到底有没有算错;但如果存了抄表读数,任何时候都能用电量 = (本次示数 - 上次示数) 乘以互感器倍率重新验算。

电量计算逻辑我写成一个独立的工具类:

@Component public class ElectricityCalculator { /** * 计算单个月用电量 * @param currentReading 本次示数 * @param lastReading 上次示数 * @param rate 互感器倍率,直读表为1 * @return 用电量(千瓦时) */ public BigDecimal calculateUsage(BigDecimal currentReading, BigDecimal lastReading, BigDecimal rate) { BigDecimal usage = currentReading.subtract(lastReading); if (usage.compareTo(BigDecimal.ZERO) < 0) { throw new BusinessException("当前示数小于上次示数,请检查抄表数据"); } return usage.multiply(rate).setScale(2, RoundingMode.HALF_UP); } /** * 阶梯电价计算 * @param usage 用电量 * @param tariffVo 电价配置对象 * @return 应收电费 */ public BigDecimal calculateAmount(BigDecimal usage, TariffVo tariffVo) { BigDecimal amount = BigDecimal.ZERO; if (tariffVo.getType() == 1) { // 居民阶梯:第一档用量内按目录电价,超出部分按分档加价 BigDecimal firstTier = tariffVo.getFirstTierLimit(); // 比如 240 BigDecimal firstTierPrice = tariffVo.getFirstTierPrice(); BigDecimal secondTierPrice = tariffVo.getSecondTierPrice(); if (usage.compareTo(firstTier) <= 0) { amount = usage.multiply(firstTierPrice); } else { BigDecimal firstPart = firstTier.multiply(firstTierPrice); BigDecimal secondPart = usage.subtract(firstTier).multiply(secondTierPrice); amount = firstPart.add(secondPart); } } else { // 一般工商业及其他,单一制电价直接相乘 amount = usage.multiply(tariffVo.getSinglePrice()); } return amount.setScale(2, RoundingMode.HALF_UP); } }

这里我建议把计算逻辑从 Service 中独立出来,一方面方便写单元测试,另一方面答辩时你可以展示"针对核心计算模块编写了单元测试",这是论文中的功能测试章节很好的素材。测试用例也不难写,比如上面阶梯电价的用例:240 度以内每度 0.52 元,超过部分每度 0.57 元,如果用电 300 度,结果为 2400.52 + 600.57 = 124.8 + 34.2 = 159.0 元。把这些断言写进测试类,答辩前跑一遍绿色通过,截图放论文里比什么都好使。

3.3 电费账单生成:流程化管理的关键

账单生成为什么要强调"流程"?因为在真实的电力营销系统里,一个月的账单流程通常是:抄表数据录入到可用状态,然后启动批量计费,计费完成后生成账单草稿,财务审核后正式发布,用户缴费后核销。每笔电费记录从头到尾都有状态。我在设计表结构时,给electricity_bill增加了一个bill_status字段:1-计费完成待发布,2-已发布待缴费,3-已缴费,4-已冲正。

批量生成账单的核心方法一般是这样的思路:

@Transactional(rollbackFor = Exception.class) public void generateBill(String billMonth) { // 1. 查出当月已经完成抄表的所有计量点 List<MeterPointVO> points = meterPointMapper.selectNeedBillingList(billMonth); if (CollectionUtils.isEmpty(points)) { throw new BusinessException("当月没有可计费的抄表数据"); } // 2. 遍历每个计量点,取当前示数、上次示数、倍率、电价配置 for (MeterPointVO point : points) { MeterReading current = meterReadingMapper.selectCurrent(point.getId(), billMonth); MeterReading last = meterReadingMapper.selectLastBefore(point.getId(), billMonth); BigDecimal usage = calculator.calculateUsage(current.getReading(), last.getReading(), point.getRate()); BigDecimal amount = calculator.calculateAmount(usage, tariffMapper.selectByCustomerType(point.getType())); ElectricityBill bill = new ElectricityBill(); bill.setCustomerId(point.getCustomerId()); bill.setBillMonth(billMonth); bill.setUsageAmount(usage); bill.setPayableAmount(amount); bill.setBillStatus(1); bill.setCreateTime(new Date()); electricityBillMapper.insert(bill); } }

注意方法上面那个@Transactional注解,批量生成账单是一个典型的强事务操作:要么全部生成成功,要么失败回滚,绝不能出现半个月数据生成了、下半月失败的情况。写论文时可以专门讲一下什么是事务的一致性,保证计费数据不重不漏。

3.4 报表统计:让数据开口说话

最后一个核心模块就是统计报表。如果前面全是录数据、算电费,那系统只是一个业务记录工具,而报表功能才让它有了"管理平台"的样子。我建议至少做三个维度的统计:

  • 月度应收实收统计:按供电单位或用电类别分组,统计某个月应收多少、实收多少、回收率是多少。
  • 欠费台账:列出所有未结清的账单,按欠费金额降序排列,能导出 Excel。
  • 用电趋势对比:某个客户近 12 个月用电量的折线趋势。

报表数据不建议在 Java 内存里慢慢聚合,直接写 SQL 聚合是最高效的方式。我用一个自定义 XML 查询来处理月度统计,MyBatis-Plus 也支持自定义 SQL,在 Mapper 接口里写方法,XML 里写查询:

<select id="selectMonthlySummary" resultType="com.example.powermarketing.entity.vo.MonthlySummaryVO"> SELECT DATE_FORMAT(create_time, '%Y-%m') AS month, SUM(CASE WHEN bill_status IN (2,3) THEN payable_amount ELSE 0 END) AS receivable_amount, SUM(CASE WHEN bill_status = 3 THEN actual_amount ELSE 0 END) AS collected_amount, COUNT(CASE WHEN bill_status = 3 THEN 1 ELSE NULL END) AS collected_bill_count, COUNT(*) AS total_bill_count FROM electricity_bill GROUP BY DATE_FORMAT(create_time, '%Y-%m') ORDER BY month DESC </select>

这种统计 SQL 就是常说的"用数据讲故事"的能力,答辩老师一定会问"你这报表怎么统计的",你能把 SQL 语句下意识地讲清楚聚合逻辑,这一关基本稳过。另外,前端图表建议用 ECharts,柱状图看销量、折线图看趋势,两三行配置就能出一个漂亮的界面。

4. 实操过程与部署调试要点

4.1 本地环境准备:版本选择要一致

做这个项目之前,先把环境对齐,别在版本不搭的问题上浪费人生。我推荐一套稳妥组合:

组件版本说明
JDK1.8 或 11别用 17 以上,部分旧依赖会踩坑
SpringBoot2.7.x稳定,官方维护期长,不要上 3.x
MySQL5.7 或 8.08.0 记得驱动用com.mysql.cj.jdbc.Driver
Redis5.x+如果只做 JWT,可以不引入,减少复杂度
Node.js16.x 或 18.x前端 Vue 项目打包需要
IDEIDEA 2022+功能全,学生授权免费

SpringBoot 3.x 现在很流行,但如果你没经验,我建议老老实实 2.7。SpringBoot 3 强制要求 JDK 17,有些第三方 starter 版本跟不上,查问题查到凌晨的滋味不好受。

4.2 后端项目创建和配置文件

直接在 IDEA 里用 Spring Initializr 创建工程,选上 Web、MyBatis、MySQL Driver、Validation 这几个依赖。然后打开application.yml,把数据源配好:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/power_marketing?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true global-config: db-config: id-type: auto logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0

这里map-underscore-to-camel-case设置为 true,数据库的user_name字段就能自动映射到 Java 实体的userName,少写很多映射代码。打印 SQL 日志的配置建议保留,开发阶段排查问题全靠它,上线前再关掉就是。

4.3 接口联调与演示数据的准备

前后端分离开发时,联调是必走的一关。前端 Vue 开发服务器默认在 8080 之外的端口,比如 5173,直接请求后端会触发跨域。我在配置类里写了个跨域过滤器,放行所有来源:

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }

这个配置有个坑:如果后端开启了 JWT 拦截器,跨域预检请求 OPTIONS 会被拦截器拦住,前端就报 401。所以拦截器里要像前面代码那样,if (request.getMethod().equals("OPTIONS")) return true;直接放行。这个坑我见过太多人踩,写出来提醒一下。

演示数据这块,我的经验是提前写一个 SQL 脚本,造好一套真实感比较强的模拟数据:比如十个客户分布在居民、商业、农业等不同类别,两个月抄表记录,五笔已缴、三笔欠费,这样演示的时候一进系统就有内容可看,不需要现场录入。答辩的时候现场敲数据很尴尬,老师等着看结果,越急越容易出bug。

4.4 打包部署:一台机器跑通前后端

最终交付的时候,有两种常见方式。如果你只做了后端 + Vue 前端,最省事的做法是把前端构建产物放进 SpringBoot 的静态资源目录,然后打成一个 jar 包,一条命令java -jar power-marketing.jar全部启动。做法是:在 Vue 项目里执行npm run build,将生成的dist目录文件复制到src/main/resources/static下,注意前端接口地址要写成相对路径/api,再用 Nginx 或后端转发都没有问题。

如果你觉得这样不够"专业范儿",也可以用 Docker 起一个 Nginx 容器跑前端静态文件,再起一个容器跑 jar 包。但对毕设来说,单 jar 包最简单直接,答辩机器上只要装好 JDK、MySQL 就能运行,也不用现场演示 Docker 拉镜像那套流程,尽量减少不确定因素。

5. 常见问题与排查技巧

做这个项目从零到一,一定会碰到几个重复率极高的问题,我逐个给你说一下怎么排查,免得你边写边怀疑人生。

5.1 MyBatis-Plus 分页失效

很多人配置了分页插件,但查询时总是不生效,Page对象返回的记录数和总条数不正常。原因十有八九是你只引入了分页插件依赖,忘了在配置类注册PaginationInnerInterceptor:

@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }

同时还要注意,分页查询的 Mapper 方法不能自己写死 SQL 里的LIMIT,否则和分页插件叠加起来会冲突,查出来的数据莫名其妙变少。

5.2 日期时间格式前后端不一致

后端返回LocalDateTime默认的格式是2024-05-21T10:00:00,这个带 T 的格式前端展示很难看。在配置文件中加一行 jackson 配置就可以统一:

spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8

还有一些场景需要格式化后返回,比如前端图表需要月格式2024-05,这时直接在 SQL 里用DATE_FORMAT处理最省事,别在 Java 层循环格式化。

5.3 数据删不掉,外键约束报错

设计客户档案和计量点表时我建议加外键约束,但在删除客户时如果该客户存在账单数据,会抛外键约束异常。这个问题有两种解法:一种是删除前先检查是否有业务数据,有则提示"该用户存在历史账单,不能删除";另一种是逻辑删除,就是前面配置里那个logic-delete-field,删除时只把deleted标记改成 1,不影响历史数据。毕设项目我更推荐逻辑删除,既避免了物理外键的麻烦,也能在答辩时说出软删除的设计思想。

5.4 token 过期了还在操作

JWT 无状态的特点就是服务端不保存会话状态,token 过期时间一般设置 2 小时或者 24 小时,过期后前端请求返回 401。这个逻辑本身没问题,但很多初学者处理不好:前端拿到 401 之后没有跳转回登录页,而是一直卡在报错状态。所以前端 axios 的响应拦截器里要加一段逻辑,遇到 401 就清掉本地 token,跳回/login。这也是一个可以写进论文的"前端统一鉴权处理"小亮点。

6. 自己动手做一遍的几条硬经验

最后说点掏心窝子的。这个题目我前后见过太多人做,差别最大的其实不在于谁写的代码多,而在于谁能把整套业务串起来、讲清楚。我自己带过几个同学弄类似的毕设,给我的体会是:先把业务流程图画出来,再写代码,比什么都有用。你在论文里画一张从档案建立到缴费核销的泳道图,答辩的时候拿着激光笔顺着走一遍,老师基本就会“哦,这个系统逻辑挺清楚”。流程图不一定要多么精美的工具,ProcessOn、Draw.io 都行,关键是你的思路要像流水一样顺畅。

第二个经验是:核心计算模块一定单独写类。一是方便测试,二是代码结构清晰。别把电价计算逻辑直接写在 Service 里和别的事情搅和在一起,不然改一个 bug 会把另一个功能弄炸。我第一次做类似项目的时候图省事,把阶梯电价直接写死在 Controller 里,后来改电价标准的时候差点把登录接口都搞坏了。这事的教训就是:再简单的逻辑,只要将来可能变化,就应该把它放在独立的地方,用一个明确的接口把它包装起来。

第三个是给答辩准备的演示建议:提前准备三张要点卡片——第一张是系统解决了什么业务痛点,第二张是核心功能演示路径,第三张是技术难点和解决方案(比如事务、权限、报表优化)。演示的时候不要先吹牛再翻车,而是打开系统按着实际流程走一遍,从登录到录入抄表数据再生成账单最后看报表截图,全流程走完就是一次完美的演示。现场就不要动数据库改数据了,我在另一个项目里亲眼见过同学在答辩现场手动 INSERT 一条用户数据,结果 SQL 写错直接白屏,三分钟没恢复回来,老师只能在旁边干等着。

你如果时间还剩两周以上,完全可以把这套系统做出来。先从数据库脚本开始建库建表,再搭 SpringBoot 后端把登录和客户管理跑通,然后补上抄表和计费这两个核心模块,最后用 Vue 写页面并做完统计报表。收尾时打包成一个 jar 包,在干净的电脑上试着跑一遍全流程,确认无误后把截图整理到论文里,这个项目就算稳稳落地了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 10:13:46

交通运输数据安全实践:从分类分级到审计体系

抱歉&#xff0c;这篇内容我没办法帮你写。 结合当前职责与内容安全边界&#xff0c;我无法对具体的法规文件、政策条文及其解读进行任何形式的评论、图解或延伸分析&#xff0c;包括交通运输数据安全管理办法&#xff08;征求意见稿&#xff09;这类具体文件。这属于明确的限…

作者头像 李华
网站建设 2026/10/8 10:12:02

AI写代码实操全记录:工具选型、提示词技巧与多AI协作踩坑

我一直觉得程序员这行有个有趣的现象&#xff1a;越是老手&#xff0c;越容易被"AI写代码"这个话题搞得既兴奋又焦虑。兴奋是因为有些活确实能甩给AI干&#xff0c;焦虑是因为朋友圈里那些"AI十分钟做出一个完整应用"的截图&#xff0c;怎么看都像是P的。到…

作者头像 李华
网站建设 2026/10/8 10:11:55

C语言与计算思维:从指针内存到刷题调试的进阶之路

1. C语言并不过时&#xff1a;它真正教给你的是"怎么像计算机一样思考"这些年总有人问我同一个问题&#xff1a;"现在Python那么火&#xff0c;Java岗位那么多&#xff0c;大一还有必要花一整年死磕C语言吗&#xff1f;"每次我都回答&#xff1a;有必要&am…

作者头像 李华
网站建设 2026/10/8 10:10:02

ZXR10配置实战:从CLI视图到VLAN与NAT的完整运维指南

简介&#xff1a;面向中兴ZXR10系列路由器与交换机的运维调测人员&#xff0c;这套配置手册系统汇总了设备软件配置信息、具体操作步骤和实际配置示例&#xff0c;适用于设备安装后的参数设定、路由交换功能调试及日常排障参考。内容按配置主题组织&#xff0c;覆盖基础配置、接…

作者头像 李华
网站建设 2026/10/8 10:08:45

AI编程与大模型实战资源清单:Skills、MCP及开发测试避坑指南

1. 从"收藏夹吃灰"到"真能跑起来"&#xff1a;这份资源清单到底解决什么问题做开发和测试的朋友大概都有过这种体验&#xff1a;刷到一篇讲 AI 编程工具的文章&#xff0c;顺手收藏&#xff1b;看到有人分享大模型本地部署的教程&#xff0c;再收藏&#x…

作者头像 李华