基于Java的工地协同管理系统设计与实现——考勤、环境监测与协同办公一体化方案
计算机毕业设计里“基于Java的工地协同管理系统”是出现频率很高的一类题目。它看起来不算难——无非是做个Web系统把考勤、环境监测、协同办公堆在一起但真打开需求文档你会发现考勤要带位置判定环境监测要处理设备数据协同办公要管任务状态流转三个模块揉在一起业务边界和工作量一下就不一样了。我前后带过不少做这类题目的同学也参与过真实工地管理平台的改造今天就从需求拆解开始把整个系统的设计思路、数据库结构、核心代码和部署细节完整过一遍给准备做这类项目的同学一条可以直接上手的实现路线。文章里所有方案都基于Java技术栈和B/S架构这也是多数高校毕业设计默认的技术组合照这个思路做答辩时不会被问倒。1. 先把业务想清楚这个系统到底要管哪几件事1.1 题目拆解三个关键词对应三套完整业务很多同学拿到题目就急着建项目、建表这是最大的坑。你先把标题读三遍——工地协同管理、工人考勤、环境监测一体化。这其实是三套相对独立、又需要数据打通的业务工人考勤解决“人来了没有、干到几点、在哪个工地干的”的问题。传统工地上班组长拿纸笔点名月底再汇总算工时效率低还容易扯皮。系统要做的是让工人在进入工地时打卡后台自动记录时间和位置月底自动生成考勤统计表。环境监测解决“工地现场的环境指标是否合规”的问题。主要关注扬尘PM2.5、PM10、噪声、温度湿度、风速风向等。政府监管和工地自身安全都需要这些数据超标时还要自动报警。协同管理解决“项目里各方角色怎么配合”的问题。包括任务派发、进度反馈、安全隐患上报、公告通知等。工地上有项目经理、技术负责人、安全员、班组长、普通工人每个角色看到的信息和能做的事都不一样。把这三个业务拆开之后系统边界就清楚了它不是一个泛泛的“工地管理系统”而是以项目为维度把人员、设备、任务串联起来的平台。1.2 角色权限先定人有谁再定功能给谁我见过很多同学上来就写代码结果做到登录模块才发现不知道要设计几个角色。建议在动手之前先把角色清单列清楚。这套系统里至少要包含以下几种角色角色核心诉求典型操作系统管理员维护基础数据创建项目、添加用户、配置监测点项目经理掌握全局进度查看考勤汇总、环境报表、任务进度安全员发现和跟进隐患上报问题、发起整改、查看环境告警班组长管理班组工人审核考勤、派发班组任务、补卡审批工人完成打卡和任务上下班打卡、查看个人工时、接收通知这个角色划分不是拍脑袋它决定了后面数据表设计里要不要有“班组”表、任务表里要不要加“指派人”和“审核人”两个字段、权限拦截器要配几套规则。建议在第一周就把角色和权限矩阵画出来哪怕写在纸上也行后面所有功能都会围绕这个矩阵展开。2. 技术选型背后的取舍Java和B/S架构为什么是这套题的标配2.1 Java技术栈不是因为它最新而是因为它最稳题目里明确写了Java那后端语言没有悬念。但Java生态里还分很多路线这里需要做个选择传统SSMSpring Spring MVC MyBatis还是Spring Boot。我的建议是直接用Spring Boot。理由很实际毕设项目时间紧Spring Boot的自动配置能省掉大量XML配置内嵌Tomcat让部署变得非常简单。你可能看到网上很多老教材还在讲SSM那些内容不是不能学而是对于“完成一个能跑的系统”来说效率太低。Spring Boot学习成本不高而且答辩时老师也完全认可以现在企业里新项目基本都走Spring Boot这反而是一个加分项。版本选择上推荐Java 8或Java 11配Spring Boot 2.x原因只有一个资料多。你遇到任何报错去搜索引擎一搜就能找到答案。Spring Boot 3.x虽然新但要求Java 17有些老版本的第三方库会不兼容对于毕设来说没必要冒这个险。2.2 B/S架构为什么工地场景特别适合浏览器访问B/S架构就是Browser/Server所有功能通过浏览器访问客户端不需要安装任何软件。工地场景有个天然痛点人员分散在不同项目上可能今天在这个工地明天在那个工地如果装C/S客户端光是版本更新就能折腾掉半条命。B/S架构的优势在这里完全体现出来只要有浏览器手机、平板、工地办公室的旧电脑都能打开系统。尤其考勤打卡这个功能工人在手机浏览器里打开页面就能定位打卡不需要专门开发App省掉一大块工作量。这也决定了系统的开发模式部署一台服务器数据库和Web应用都放上面前端浏览器负责展示和交互。答辩时老师问“为什么选B/S架构”你就从维护成本、跨平台访问、实时数据共享三个角度回答肯定没问题的。2.3 前端怎么选别为了“好看”引入一套复杂框架很多同学纠结前端要不要用Vue、Element UI做前后端分离。我的态度很明确如果你对Vue不熟坚决不用如果熟悉可以加分。原因在于毕设的核心是证明你掌握了一套完整的开发流程而不是前端炫技。用JSP或Thymeleaf模板引擎 Bootstrap或LayUI一样能做出像样的界面。LayUI特别适合这种管理类系统表格、表单、弹窗、日期选择器都现成的稍微调一调就很好看。前后端分离的方案意味着你要同时维护两套项目、处理跨域、考虑Token鉴权工作量直接翻倍。除非你对Vue已经很有把握否则别给自己挖坑。我见过不止一个同学系统写到一半发现前端搞不定又回头改成模板引擎白白浪费两周时间。3. 数据库建模考勤、环境、协同三块业务怎么落到表里3.1 基础表设计用户、项目、班组先打好地基数据库是整套系统的地基表结构设计错了后面全得返工。先看基础表这三张表是几乎所有业务都要关联的用户表sys_user字段包括用户ID、姓名、手机号、密码加密存储、角色ID、所属班组ID、身份证号、入职时间。这里要特别注意密码必须加密建议用MD5加盐或BCrypt但很多毕设的同学会把密码明文存到数据库里——这个被答辩老师看到非常扣分。项目表project字段包括项目ID、项目名称、项目地址、经纬度、开工日期、计划竣工日期、项目经理ID。项目表里的经纬度字段很关键后面做考勤位置判定、环境监测点关联都要用到。班组表team字段包括班组ID、班组名称、班组长ID关联用户表、所属项目ID。工人和班组是多对一的关系考勤按班组汇总后班组长可以比较容易地审核工时。3.2 考勤业务表记录每一次打卡也记录每一次异常考勤表attendance是这套系统的核心业务表字段设计绝不能草率。我建议至少要包含考勤ID、用户ID、项目ID、打卡时间、打卡类型上班/下班、打卡经度、打卡纬度、考勤状态正常/迟到/早退/缺勤、是否有效、备注。这里有两个容易忽略的点。第一经纬度必须记录。既然考勤强调位置打卡就得把每次打卡的位置存下来不然以后有争议时说不清楚。数据库里经纬度建议用DECIMAL(10,6)类型精度够用。第二考勤状态不要实时计算而是每天凌晨用定时任务统一计算一遍。因为“迟到”“早退”需要和项目规定的上下班时间比较实时算的话逻辑会非常分散统一批量处理更清晰。除了正常的打卡记录还要有一张补卡申请表attendance_adjust包括申请ID、用户ID、原始日期、申请类型补卡/更正、原因、审批状态、审批人ID。工人如果忘记打卡可以发起补卡申请班组长审批后修改考勤记录。这个流程虽然简单但能体现你对业务场景的理解写字数不愁。3.3 环境监测表设备、指标、实时值、阈值分开存环境监测模块有三张核心表很多同学会把它们合成一张这是不科学的。设备表device设备ID、设备编号、设备名称、设备类型扬尘/噪声/温湿度/风速、安装位置经纬度、所属项目ID、状态在线/离线、添加时间。环境监测数据表env_record记录ID、设备ID、项目ID、PM2.5数值、PM10数值、噪声数值、温度、湿度、风速、采集时间。这里要注意环境监测数据是高频数据如果每个指标单独一行数据量会很大按设备每行存一个完整快照查询起来更直观。告警记录表env_alarm告警ID、设备ID、项目ID、告警类型PM2.5超标/噪声超标等、告警数值、阈值、告警时间、处理状态未处理/已处理、处理人ID。告警表和监测数据表分开存是为了避免每次查询告警都要扫描海量的环境数据。环境阈值建议单独建一张配置表env_threshold字段包括指标类型、上限阈值、下限阈值、所属项目ID。因为不同项目可能有不同的环保要求硬编码在代码里后期不好改。3.4 协同管理表任务有状态问题有闭环协同管理的核心是任务和问题设计上需要体现状态流转。任务表task任务ID、任务标题、任务内容、发布人ID、执行人ID班组长、所属项目ID、优先级、状态待开始/进行中/已完成/已验收、计划完成时间、实际完成时间、创建时间。任务表的状态字段很关键协同的本质就是状态在不同人之间传递。问题上报表issue问题ID、上报人ID、问题类型安全隐患/质量问题/其他、问题描述、图片地址、位置、状态待处理/整改中/已完成/已关闭、指派人ID、处理结果、上报时间、关闭时间。问题上报表里加一个图片地址字段很有必要工地上发现隐患拍张照片上传比写一百个字都管用。通知消息表message消息ID、接收人ID、消息类型任务通知/告警通知/系统通知、消息内容、关联业务ID、是否已读、创建时间。站内信并不复杂但这张表能撑起协同模块的“消息感”让整个系统看起来完整很多。这十几张表之间其实不需要太复杂的外键约束。说实话在真实项目里外键约束往往是用逻辑维护的为了性能会放弃数据库级别的外键。但毕设建议还是把外键加一些答辩时老师看E-R图有外键的模型更完整。4. 工人考勤模块距离判定打卡的完整实现4.1 打卡方案怎么选GPS定位是最适合毕设的路径工地考勤的打卡方式现实中常见的有三种GPS定位打卡、二维码/蓝牙打卡、人脸识别打卡。对于毕设来说人脸识别直接劝退涉及硬件和算法二维码打卡虽然简单但不能体现“人在工地”的核心逻辑。建议做GPS定位打卡。具体流程是工人在手机浏览器打开打卡页面前端通过HTML5的Geolocation API获取当前位置坐标和后端提前配置好的项目坐标比较如果距离小于设定的阈值比如200米就允许打卡否则提示“不在项目范围之内”。这个方案既贴近真实业务技术上又完全可落地不需要任何额外的硬件设备。4.2 距离计算的核心公式Haversine两个经纬度坐标之间的距离不能用简单的勾股定理算因为地球是球面。这里要用Haversine公式代码不多但很能体现功底。private static final double EARTH_RADIUS 6371000; // 地球半径单位米 /** * 计算两个经纬度坐标之间的距离 * param lat1 打卡点纬度 * param lng1 打卡点经度 * param lat2 项目点纬度 * param lng2 项目点经度 * return 距离单位米 */ public static double getDistance(double lat1, double lng1, double lat2, double lng2) { double radLat1 Math.toRadians(lat1); double radLat2 Math.toRadians(lat2); double a radLat1 - radLat2; double b Math.toRadians(lng1) - Math.toRadians(lng2); double s 2 * Math.asin(Math.sqrt( Math.pow(Math.sin(a / 2), 2) Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); return s * EARTH_RADIUS; }这段代码放到工具类里打卡接口里一行调用就能判断。注意前端传来的经纬度千万不要直接信任因为浏览器定位有可能拿不到或拿到的是缓存的旧位置后端必须做参数校验和空值处理。4.3 打卡接口的实现逻辑打卡接口的核心逻辑是查询当前用户所在的项目 - 取项目的经纬度 - 计算与打卡位置的距离 - 判断是否在阈值内 - 判断当前时间是否合理 - 写入考勤记录。PostMapping(/attendance/checkIn) public Result checkIn(RequestBody AttendanceCheckInVO vo, HttpSession session) { // 1. 获取当前登录用户 User currentUser (User) session.getAttribute(currentUser); if (currentUser null) { return Result.error(请先登录); } // 2. 判断打卡时间是否合理 LocalTime now LocalTime.now(); if (vo.getType() 1 now.isAfter(LocalTime.of(9, 0))) { return Result.error(已经超过上班打卡时间); } // 3. 查询用户所属班组对应的项目 Team team teamMapper.selectById(currentUser.getTeamId()); Project project projectMapper.selectById(team.getProjectId()); // 4. 计算与项目位置的距离 double distance DistanceUtils.getDistance( vo.getLatitude(), vo.getLongitude(), project.getLatitude(), project.getLongitude()); // 5. 判断距离阈值默认200米 if (distance 200) { return Result.error(当前位置距离项目地址过远无法打卡); } // 6. 保存考勤记录 Attendance attendance new Attendance(); attendance.setUserId(currentUser.getId()); attendance.setProjectId(project.getId()); attendance.setCheckTime(new Date()); attendance.setType(vo.getType()); attendance.setLatitude(vo.getLatitude()); attendance.setLongitude(vo.getLongitude()); attendanceMapper.insert(attendance); return Result.success(打卡成功); }这段逻辑里有几个细节上班打卡时间超过9点是否直接拒绝现实中可能是允许打迟到卡而不是直接拒签。建议做成超过时间也能打卡但考勤状态被标记为“迟到”。这样对工人更友好也符合实际场景。4.4 考勤统计与导出月底算工时是最后一步考勤统计很简单但很繁琐。建议写一个定时任务每天凌晨跑一遍把昨天的考勤记录按“用户 项目”分组计算每个人的出勤状态和有效工时写入一张考勤日汇总表。月底想生成报表时直接查日汇总表聚合即可性能快很多也避免月结时全表扫描。导出功能用EasyExcel或者POI都可以。EasyExcel更轻量推荐用它做导出。如果你对POI比较熟也完全OK。导出时要设置列宽、表头样式导出的Excel打开不乱码这个细节虽然不起眼但演示时很加分。5. 环境监测模块模拟采集到阈值告警的闭环5.1 数据从哪来毕设的最佳方案是内置模拟数据环境监测模块最容易卡住的地方是没有真实传感器设备数据从哪里来我的建议是写一个数据模拟器用定时任务每10秒向环境监测表插入一条模拟数据。模拟数据要做得真实一些比如PM2.5数值在30到150之间随机波动噪声在50到90分贝之间随机波动温度在15到35度之间浮动。可以加一点“趋势”逻辑比如噪声在早中晚三个时段的基准值不一样这样数据看起来就更真实。这个模拟器本质上是调试工具但它也承担了“设备数据接入层”的角色。将来接真实设备只需要把模拟器的定时任务替换成接收设备HTTP上报的接口就行其他业务代码完全不用动。答辩时这样解释“设备接入的扩展性”老师会认可。Component public class EnvironmentDataSimulator { Scheduled(fixedRate 10000) // 每10秒执行一次 public void generateData() { ListDevice devices deviceMapper.selectOnlineDevices(); for (Device device : devices) { EnvRecord record new EnvRecord(); record.setDeviceId(device.getId()); record.setPm25(30 new Random().nextInt(120)); record.setPm10(50 new Random().nextInt(200)); record.setNoise(50 new Random().nextInt(40)); record.setTemperature(20 new Random().nextInt(15)); record.setHumidity(40 new Random().nextInt(30)); record.setWindSpeed(1 new Random().nextDouble() * 5); record.setCollectTime(new Date()); envRecordMapper.insert(record); // 顺带检查是否超标如果超标就插入告警记录 checkThresholdAndAlarm(device, record); } } }用Spring自带的Scheduled注解就能实现定时任务不需要额外引入Quartz除非你要做更复杂的调度策略。注意固定延时和固定频率的区别这里用Scheduled(fixedRate 10000)表示每10秒触发一次如果上一轮还没执行完会等执行完再算周期。数据插入量不大不用考虑并发问题。5.2 实时监测页面轮询还是WebSocket实时监测页面需要大屏展示效果地图上标出监测点侧边栏显示实时数据表。数据刷新方案有两种第一种是前端定时轮询每隔5秒请求一次接口返回最新的环境数据。这种方案实现简单几行代码搞定。第二种是WebSocket服务器主动推送数据给浏览器。实时性更好但代码复杂度高不少。对于毕设来说我推荐轮询理由不变——能用稳定简单方案实现的功能不要引入复杂技术。如果评委老师问“为什么不用WebSocket”你可以回答“当前数据采集频率是10秒一次5秒轮询足以满足需求WebSocket适合更高频的数据推送是一个可扩展方向”。这个回答滴水不漏。轮询接口注意一个细节每次只查最近10分钟的数据不要每次查询都全表扫。加一个时间条件配合索引数据量再大也不怕。接口返回的字段要和前端图表库对接好常用的前端图表库是ECharts它对折线图、柱状图、仪表盘的支持都很好页面做出来像模像样。5.3 阈值告警告警触发了还要能处理闭环告警的逻辑在模拟器里已经带了插入数据后比对阈值表如果超标就插入告警记录同时给安全员发一条站内消息。这里比较容易忽略的是告警的重复触发问题——如果PM2.5连续三次都超标是不是要生成三条告警真实场景下肯定不能这么干。建议的逻辑是相同设备、相同告警类型、并且有一条“未处理”的告警记录存在时不再生成新告警只在原来那条记录上更新最新的超标数值。只有等安全员处理完下一次超标才能生成新的告警。这样既避免了告警轰炸又保留了完整的处理流程。告警处理页面要能做三件事查看告警详情、标记处理、填写处理措施。安全员看到告警后先在系统里确认然后去现场处理处理完填写处理记录形成闭环。这个“闭环思维”在答辩中非常常见老师的关注点往往不只是“能不能报警”而是“报警之后怎么办”。你把问题上报、处理、归档的完整流程做出来整个系统的深度就出来了。6. 协同管理任务派发、问题上报与消息通知6.1 任务派发与状态流转从创建到验收每一步都有负责人任务模块是协同管理的核心。项目经理登录系统后点击“新建任务”填写任务标题、内容、执行人班组长、优先级、计划完成时间提交后任务状态为“待开始”。班组长登录后看到指派给自己的任务点击“开始任务”状态变为“进行中”。任务完成后点击“申请完成”状态变为“已完成”等待项目经理验收。项目经理验证工作成果后点击“验收通过”状态变为“已验收”。如果验收不通过任务回到“进行中”并附带验收意见。这个状态流转本质上是有限状态机建议用Java枚举来定义状态避免字符串散落在代码的各处public enum TaskStatus { PENDING(0, 待开始), IN_PROGRESS(1, 进行中), FINISHED(2, 已完成), ACCEPTED(3, 已验收), REJECTED(4, 已驳回); private final int code; private final String desc; TaskStatus(int code, String desc) { this.code code; this.desc desc; } public int getCode() { return code; } public String getDesc() { return desc; } }更新任务状态的时候先在代码里判断当前状态能不能跳到目标状态。比如“待开始”可以直接跳到“进行中”但“已完成”不能直接跳到“已验收”必须经过项目经理的验收操作。状态机的校验逻辑写清楚答辩时这就是一个技术亮点。6.2 问题上报与整改跟进安全员的日常都在这问题上报模块的逻辑和任务模块类似但强调“隐患”属性。安全员在巡查时发现问题上传照片和问题描述系统自动定位到上报人所处的项目生成一条问题记录状态为“待处理”。项目经理看到问题后指派给对应的班组长整改状态变为“整改中”。班组长整改完成后上传整改照片和说明状态变为“已完成”。最后安全员重新核查确认整改到位后点击“关闭”状态变为“已关闭”。如果整改不合格可以驳回重新整改。这个模块的加分点在于问题报告单上要体现“上报时间、整改时限、超期未处理提醒”。可以在定时任务里加一个扫描逻辑发现“整改中”状态超过7天的问题自动给项目经理发一条提醒消息。这个细节做完整套系统的“智能感”就出来了。6.3 站内消息通知不靠吼系统里都有记录工地上之前靠微信群和电话信息容易漏。系统里加一个站内信模块所有业务事件都能触发消息通知任务被指派时通知执行人、任务被验收时通知执行人、告警产生时通知安全员、审核被打回时通知申请人。站内信表的字段前面已经设计过关键是要加“是否已读”和“关联业务ID”两个字段。“关联业务ID”让消息可以点击跳转到对应的任务或告警详情页这比单纯的文字提醒体验好很多。实现上很直接在相应业务代码里调用messageMapper.insert()插入一条记录即可。未读消息的角标数可以在系统顶部统一展示前端用定时轮询查一下未读数有新消息时红点提示。这个体验细节很实用演示的时候特别抓眼球。7. 前后端联调与部署把系统真正跑起来7.1 登录拦截与权限判断别让工人看到项目成本数据系统里角色多权限控制是躲不开的。最基础的做法是用Spring MVC的拦截器写一个LoginInterceptor在会话中取不到用户就重定向到登录页。这个拦截器本质上干一件事把所有未登录的请求挡住。更细一层的权限控制是角色判断。比如“新建任务”按钮只有项目经理角色才显示“补卡审批”只有班组长和项目经理才能操作“环境告警处理”只有安全员才能点击。前端隐藏按钮是一方面后端接口也要校验。可以用AOP自定义一个RequireRole注解标注在需要权限的方法上拦截器里根据注解判断角色实现简洁且可复用。我遇到过一些同学前后端分离的接口不校验权限任何人调用接口都能拿到全部数据。答辩老师打开浏览器控制台直接调用一下接口数据就暴露了这种演示事故非常伤。后端接口的权限校验千万别省。7.2 跨域与配置绕过前端调试时最大的坑如果你是前后端分离开发比如前端Vue跑在8080端口后端Spring Boot跑在8081端口就会遇到跨域问题。解决办法是后端写一个CorsConfig允许指定地址跨域访问。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(http://localhost:8080) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }如果用的还是JSP模板引擎模式前后端同源基本不会遇到跨域问题。这也再次印证了前面的建议模板引擎方案确实省事。7.3 打包部署本地能跑只是第一步服务器上能跑才是关键答辩前一定要把系统部署到云服务器或者至少是独立的环境里别再用IDE里的Debug模式演示。用Spring Boot的话打包极其简单项目根目录执行 mvn clean package -DskipTests会生成一个可执行的JAR包然后在服务器上用 java -jar xxx.jar 启动。服务器环境需要注意几点JDK版本必须和本地一致建议统一用Java 8。MySQL字符集设置为utf8mb4否则中文很容易乱码。数据库初始化脚本要准备一份完整的包含所有建表语句和初始数据。答辩前在空环境上跑一遍初始化脚本确认能重现完整数据。端口要在防火墙和云服务商安全组里同时放行很多同学卡在这——本地能访问外部打不开。Linux服务器上部署推荐用systemd管理进程写一个service配置文件服务器重启后服务可以自动拉起。这个细节虽然不是毕设必考但从工程化角度看非常加分。8. 答辩与论文高频提问和容易翻车的细节8.1 五类高频问题及应答思路答辩时老师问的问题其实就那几类提前准备好应答通过率会高很多。第一类为什么用MySQL而不是Oracle答MySQL开源免费、体积小、并发性能针对中小型系统完全够用Oracle多用于大型企业级应用学习成本高且商用收费。这个回答既显示了选型的合理性又表明你了解不同数据库的定位。第二类Redis用了没有如果没用到怎么回答答当前系统的并发量下数据库加索引和连接池已经能够满足性能要求Redis缓存可以用于提升考勤统计等热点数据的查询速度是后续优化方向。千万不要硬说自己用了Redis被追问细节就露馅了。第三类系统最大的创新点在哪里答考勤的位置校验算法、环境告警的防重复机制、任务状态机的闭环设计。这三个点都是你实际实现的功能怎么说都不怕。第四类如果同时有1万人打卡系统会怎样答当前架构下数据库连接池会成为瓶颈。优化方案是引入消息队列削峰比如打卡请求先入RabbitMQ再由消费者异步写入数据库同时用Redis记录每日打卡状态避免重复请求。能答出这个方案老师一般就不会再深挖了。第五类项目中遇到过什么困难怎么解决的答一个真实的踩坑经验最加分。比如“刚开始环境监测数据表没加索引查询历史数据非常慢后来加了采集时间字段的组合索引查询效率提升明显”。这种基于真实验证的回答比背概念强得多。8.2 演示现场最容易翻车的三件事演示是答辩的临门一脚翻车主要集中在三处。第一数据库服务没启动页面打开全是报错。建议答辩当天提前一小时启动所有服务并在演示前把数据库服务、后端服务、前端页面全部重新走一遍流程。不是走过一遍就行而是完整地走一遍包括登录、打卡、查数据、看告警。第二之前录入的测试数据被清空了。很多同学本地开发和演示用的是同一个数据库中间重新建表测试数据没了演示干巴巴。建议准备一套专门用于演示的数据5个用户、3个项目、一周的考勤记录、若干条任务和告警数据越接近真实越好。演示时直接展示这些数据观感上会好很多。第三端口冲突导致服务启动失败。Tomcat默认8080端口经常被占用启动时注意看日志。解决方法是换一个不常用的端口比如8088同时把前端所有请求地址都改成新端口。论文方面结构可以按照课题背景与意义、相关技术介绍、需求分析、系统设计、系统实现、系统测试、总结与展望来组织。其中需求分析部分一定要有功能结构图和用例图系统设计部分要有E-R图和关键表结构说明系统实现部分要有核心代码片段和运行界面截图。论文的代码不要全部贴只贴关键逻辑并配文字说明篇幅控制在合理范围内。我最后再分享一个个人经验。带毕设时我发现凡是能把考勤闭环打卡-异常-补卡-统计完整做出来的同学答辩成绩普遍不差。原因很简单闭环代表你理解业务全流程而不只是写了几个CRUD页面。这套工地协同管理系统的三个模块最好每一个都做成“事件产生-处理-审批-归档”的完整链路哪怕功能少一点链路完整度一定要够。等你做完回过头看你会发现自己的项目管理思维和编码能力都上了一个台阶。