恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Spring Boot体育场馆预约系统毕设全攻略:从数据库到并发控制

  • 首页
  • 资讯中心
  • /
  • Spring Boot体育场馆预约系统毕设全攻略:从数据库到并发控制

相关资讯

ChatGLM3-6B LoRA微调实战:中小团队低成本落地指南 2026/10/10 4:25:05
Windows启动级权限控制:BCD配置与内核调试实战指南 2026/10/10 4:25:05
C++模板参数包与void_t:彻底解放参数列表的复用革命 2026/10/10 4:25:05

最新资讯

PaddleX 3D多模态融合检测产线(3D BEV Detection)实战:BEVFusion 推理、部署与二次开发指南
Harbor 项目贡献指南:在 AI 辅助编码时代写出能被合入的 PR
Node.js内存溢出?深入解析V8堆与FATAL ERROR的根治方案
基于FlexLM日志与Grafana的开源SolidWorks授权监控看板搭建指南
功能测试实战方法:用例设计、缺陷管理与工程实践
计算机单片机毕设实战-基于单片机的新房甲醛检测与手动自动双模式通风控制系统设计 基于单片机的室内三项环境参数阈值配置声光告警装置设计(030113)

今日推荐

Codex 总用英文回答?从 AGENTS.md 到 config.toml 的中文输出调优指南
OpenClaw 自定义插件开发完整指南(2026最新版):从 TypeScript 到 npm 发布
基于Spark的电影推荐系统全链路实战:从爬虫到Web展示

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Spring Boot体育场馆预约系统毕设全攻略:从数据库到并发控制

发布时间:2026/10/10 4:25:05
Spring Boot体育场馆预约系统毕设全攻略:从数据库到并发控制 每年毕业季辅导群里问得最多的就是这类题目。今天把这个“基于Spring Boot的体育场馆设施预约系统”从头到尾拆一遍从设计思路、数据库、核心代码到避坑清单一次说清楚。这篇文章不是给你抄代码的是帮你搞清楚这个题目到底怎么拿高分、怎么答辩不被问倒、怎么在最后一个月把项目稳稳落地。适合正在做毕设的同学、带毕设的导师参考也适合刚入行想练手Spring Boot的开发者。1. 课题拆解这个毕设到底在考你什么1.1 表面上是一个预约系统本质考察三层能力很多同学拿到题目第一反应就是“不就是增删改查吗”——对也不对。体育场馆设施预约系统确实以增删改查为主体但毕业设计考察的从来不是CRUD本身而是你在CRUD之上怎么处理业务规则、怎么设计数据关系、怎么应对并发场景。我总结下来这个题目真正考察三层能力。第一层是基本功能不能把用户、场馆、场地、预约、订单这些实体正确建模能不能用Spring Boot把它们串成完整业务流程。这一层过了项目就能跑起来。第二层是业务建模能力预约有状态状态会变化——待支付、已支付、已取消、已完成这些状态谁能触发、在什么条件下触发写的时候必须想清楚。更核心的是冲突检测同一个羽毛球场地周六下午2点到4点被A同学约了B同学再来就不能约同一时段。这个规则写不明白答辩时一问就露馅。第三层是工程能力有没有考虑过并发下单有没有处理过异常代码分层是堆在一起还是controller-service-mapper清晰分离这才是导师和评委拉开差距的地方。想清楚这三点你的时间和精力分配就有数了核心放在预约表结构和冲突检测上外观功能差不多就行。1.2 功能架构与角色权限设计基于Spring Boot的体育场馆设施预约系统角色基本就是两类普通用户和管理员。用户端要做的事很明确注册登录、浏览场馆、查看空闲场地、选择时间段提交预约、查看我的预约记录、取消预约。管理员端要做的就是场馆和场地的维护、预约记录的查看与处理、用户管理、公告发布再加一个简单的数据概览页面。权限控制在毕设里不建议折腾太复杂的框架。用一张用户表加一个role字段1表示普通用户2表示管理员然后写一个拦截器判断Session里存的用户角色权限不够就跳转到提示页。思路清晰、代码量少、答辩也讲得明白。Spring Security当然也能做但学习成本和配置成本高很多对于一个预约系统来说属于过度设计。1.3 技术选型与推荐组合技术栈网上方案很多我推荐一套最稳的组合也是我实际带项目用过多次的后端Spring Boot 2.7.x MyBatis-Plus数据库MySQL 5.7或8.0前端Thymeleaf模板 Bootstrap jQuery额外工具Lombok、Hutool工具类、Postman、Navicat为什么选这套Spring Boot 2.7配JDK8资料最多、踩坑最少网上随便一搜都是答案。MyBatis-Plus管单表CRUD非常省事不用写一堆XML把时间花在核心业务上。前端选Thymeleaf是因为前后端不分离写完一个Controller直接返回页面项目结构简单工作量远小于Vue前后端分离。如果你本身Vue很熟也可以前后端分离但要注意CORS跨域和打包问题对毕设来说不划算。2. 数据库设计把预约系统的地基打牢2.1 核心数据表及关系一个体育场馆设施预约系统核心表我用五张就能覆盖用户表、场馆表、场地表、预约表同时承载订单信息、公告表。有人喜欢把预约和订单拆成两张表理论上有道理但毕设场景里合在一张表更实用少一次Join状态管理也简单。用户表没什么好说的id、用户名、密码、昵称、手机号、角色、创建时间。密码别忘了存MD5或BCrypt加密后的值别用明文写进数据库这个细节答辩会被问到。场馆表和场地表要分开因为一个体育馆里有多个场地——羽毛球馆有1号场、2号场游泳馆可能分成浅水区和深水区。如果只建一张场地表字段冗余会非常严重。场馆表放名称、位置、简介、封面图、开放时间、状态场地表放所属场馆ID、名称、类型、每小时价格、可容纳人数、状态。预约表是整张数据库设计的核心也是出彩点下一节专门讲。2.2 预约表状态机与关键字段预约表的字段设计我建议这样预约ID、用户ID、场地ID、预约日期、开始时间、结束时间、订单金额、状态、创建时间、支付时间、取消时间、备注。这里有三点要特别强调。第一为什么时间要拆成“预约日期 开始时间 结束时间”三个字段因为预约场景天然跨天比如晚上10点到次日凌晨0点存一个开始时间一个结束时间再单独存日期查“某一天有哪些预约”最方便也方便做日期维度的统计。第二状态字段用整数规定好枚举含义。我常用的约定是0-待支付1-已支付/已预约2-已完成/已使用3-已取消4-已退款。为什么要用整数不用字符串因为判等方便、存储体积小、前端显示时用一个Map映射成中文就行。更重要的是把状态值固定在代码常量里不允许乱写后面所有业务逻辑都围绕这套状态流转展开。第三金额字段用DECIMAL(10,2)不要用float或double。这些浮点类型在计算时有精度问题金额算错在答辩演示时会非常尴尬。2.3 预约冲突检测核心设计思路先想一个问题怎么判断一个场地在某个时间段是否已被预约最直观的方案是区间判断法。查一下该场地在目标日期、目标时间段内是否存在开始时间小于目标结束时间、并且结束时间大于目标开始时间的已占用的预约记录。这个SQL写出来很经典SELECT COUNT(*) FROM reservation WHERE court_id ? AND reserve_date ? AND status IN (0, 1) -- 待支付和已支付都算占用 AND start_time ? -- 目标结束时间 AND end_time ? -- 目标开始时间但我觉得更优雅、更适合毕设演示的思路是时间片法。把每个场地每天的时间切成固定片比如从早上8点到晚上22点每2小时一片一共7片。场地表关联一张时间片表每个场地每天生成7条记录每条记录有一个is_booked字段。用户预约时其实就是选择一个未预约的时间片然后把这个时间片标记为已约。时间片法的好处非常明显。第一冲突检测从复杂的时间区间判断退化成一条等值查询逻辑大大简化写起来几乎不可能错。第二用户前端看到的界面也更直观——像电影院选座一样选时间片体验好。第三并发控制更容易做直接对这个时间片记录加乐观锁或唯一索引就能挡住重复预约。有同学会担心2小时一片不够灵活怎么办比如用户只想约1小时。解决办法是把切片粒度缩小比如每30分钟一片场地价格按片累加计算。毕设里把粒度定成1小时或2小时既好实现也够演示没必要追求极致的灵活。2.4 建表SQL参考我贴一个精简版的建表SQL直接用就可以。字段和索引我都标了注释方便你改。CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码(MD5/BCrypt), nickname varchar(50) DEFAULT NULL, phone varchar(20) DEFAULT NULL, role tinyint DEFAULT 1 COMMENT 1-用户 2-管理员, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE venue ( id bigint NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL COMMENT 场馆名称, location varchar(255) DEFAULT NULL COMMENT 位置, description text, cover_image varchar(255) DEFAULT NULL, open_time time DEFAULT NULL, close_time time DEFAULT NULL, status tinyint DEFAULT 1, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE court ( id bigint NOT NULL AUTO_INCREMENT, venue_id bigint NOT NULL COMMENT 所属场馆, name varchar(100) NOT NULL COMMENT 场地名称, type varchar(50) DEFAULT NULL COMMENT 场地类型, price_per_hour decimal(10,2) DEFAULT NULL, max_people int DEFAULT NULL, status tinyint DEFAULT 1, PRIMARY KEY (id), KEY idx_venue_id (venue_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE reservation ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL, court_id bigint NOT NULL, reserve_date date NOT NULL COMMENT 预约日期, start_time time NOT NULL COMMENT 开始时间, end_time time NOT NULL COMMENT 结束时间, amount decimal(10,2) DEFAULT NULL, status tinyint DEFAULT 0 COMMENT 0待支付 1已支付 2已完成 3已取消 4已退款, create_time datetime DEFAULT NULL, pay_time datetime DEFAULT NULL, cancel_time datetime DEFAULT NULL, remark varchar(255) DEFAULT NULL, PRIMARY KEY (id), KEY idx_court_date (court_id, reserve_date), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;如果你用时间片方案额外加一张time_slot表字段为ID、场地ID、日期、开始时间、结束时间、是否已约并在court_id date start_time上建唯一索引。3. 核心业务逻辑预约与冲突检测的实现3.1 完整预约流程梳理预约业务是整个系统的主干流程必须完整跑通。用户登录后进入场馆列表点击某个场馆查看场地详情选择日期前端显示出该场地当天的时间片挑一个空闲的确认价格后提交预约。系统要做的事按顺序是检查登录状态 - 再次检查时间片是否被占用 - 创建预约记录状态为待支付 - 标记时间片已占用 - 跳转支付页面 - 模拟支付 - 更新状态为已支付。这里注意一个细节前端已经做了空闲时间片的展示但后端在提交接口里依然要再做一次占用检查。这个检查不是多余的前端展示只是辅助后端校验才是真正的防线。这个思想在答辩时可以重点讲叫作“前端约束体验后端保证安全”。模拟支付怎么做不需要真接支付平台做一个支付页面点击“确认支付”后端把订单状态从0改成1记录支付时间再跳转到支付成功页。如果要做得出彩一点可以在支付前加一个二次确认页面显示订单概要这样演示流程会更完整。3.2 冲突检测代码的三种写法与选择冲突检测的写法至少有三种我逐一分析大家按自己的技术水平和导师口味来选。第一种基于时间段区间的SQL查询。前面已经给过SQL了用count判断是否大于0。优点是灵活支持任意起止时间缺点是人一多复杂度上来了而且区间查询容易漏掉边界情况。边界条件务必测试目标时间刚好接在前一条预约的结束时间上应该视为不冲突提前或延后一分钟就必须视为冲突。第二种基于时间片表的等值查询。提交时先查time_slot表里的某个片段is_booked是否为0是则插入预约并更新is_booked为1。这个方案的核心代码很简单// 1. 查询目标时间片 TimeSlot slot timeSlotMapper.selectOne( new LambdaQueryWrapperTimeSlot() .eq(TimeSlot::getCourtId, courtId) .eq(TimeSlot::getSlotDate, reserveDate) .eq(TimeSlot::getStartTime, startTime) ); if (slot null || slot.getIsBooked() 1) { throw new BizException(该时间段已被预约); } // 2. 创建预约记录 reservationService.create(...); // 3. 更新时间片状态 slot.setIsBooked(1); timeSlotMapper.updateById(slot);代码非常直观答辩讲解时评委理解成本低。缺点是要维护时间片表每天的新场地需要定时生成当天的时间片数据。第三种数据库唯一索引加事务兜底。在time_slot表上建唯一索引(court_id, slot_date, start_time)然后is_booked标记用0和1表示。插入预约时先将对应时间片记录更新为已约状态让数据库自己处理并发冲突。当两条相同请求同时到达时后执行那条会在更新时匹配不到行数或者违反唯一约束直接报错代码里catch住异常返回“该时间段已被预约”。第三种方案如果写在答辩里是明显的加分项因为它体现了你对并发场景的思考。3.3 并发控制抢同一个场地的两个人毕设答辩有一个极品高频问题两个用户同时点击预约同一个时间片你的系统怎么保证不重复如果代码只是“先查询is_booked 0再插入”在高并发场景下会出现问题。A和B同时查到这个时间片空闲同时往下执行插入最终两人都预约成功场地重复占用。这就是经典的竞态条件。解决办法有三个层次。最简单的给时间片表的更新语句加上条件判断做一个乐观锁式的更新UPDATE time_slot SET is_booked 1 WHERE court_id ? AND slot_date ? AND start_time ? AND is_booked 0然后判断受影响行数如果为0就说明被别人抢了。这个写法不需要额外加version字段是我最推荐的做法简单有效还讲得通。更正统的乐观锁是在表上加version字段更新时Where条件带version更新成功后version加1。类的Version字段上标Version注解MyBatis-Plus的updateById会自动带上版本条件。这种方式写起来也很干净适合作为答辩讲解素材。最硬核的是用Redis分布式锁或者数据库悲观锁。SELECT ... FOR UPDATE锁住时间片记录事务提交后再释放。但这套对毕设来说太重了除非你论文想写高并发方向否则没必要。3.4 状态流转与超时取消预约状态流转要梳理清楚答辩时画一张状态迁移图会很加分。我画文字版给你创建订单后状态为0待支付用户支付成功状态由0变成1已支付/已预约预约时间到达并结束状态由1变成2已完成用户主动取消待支付时取消为3已支付时取消为4已退款并释放场地超时未支付系统自动把状态由0改成3这里有个隐藏业务规则待支付订单不能一直占着场地不释放。比如A同学选好时间片没付款B同学看到时间片已被占就不能约了这样会导致场地资源被白白锁死。解决方式是在创建时间和预约日期之间加一个支付时限一般预约至少提前半天所以给15分钟或30分钟的支付缓冲就够了。用Spring的Scheduled注解写一个定时任务每分钟扫一次待支付订单超过时限就自动取消并释放时间片。这个定时任务很小代码十几行但它在演示时非常有用你现场下一个单不支付等定时任务跑完再刷新订单自动取消场地恢复空闲。评委一看就知道你考虑了真实业务场景。4. 从空项目到完整演示搭建与实现记录4.1 项目骨架搭建Spring Boot项目建议直接用Spring Initializr生成选Java 8、Spring Boot 2.7.x依赖勾选Spring Web、MyBatis-Plus这个在Initializr里没有需要手动加、MySQL Driver、Lombok、Thymeleaf。MyBatis-Plus依赖手动添加时注意版本兼容我之前用mybatis-plus-boot-starter 3.5.x配Spring Boot 2.7没有任何问题。如果是Spring Boot 3需要选mybatis-plus-spring-boot3-starter。项目结构按约定来即可分包清晰比什么都重要。controller包放接口service包放业务逻辑service.impl包放实现类mapper包放数据库操作entity包放实体类common包放统一返回结果和异常处理config包放配置类。实体类字段用驼峰命名数据库字段用下划线命名MyBatis-Plus默认开启驼峰映射无需额外配置。4.2 后端接口设计与统一返回接口设计要有统一规范。我建议用一个Result类包住所有返回结果结构包含code、message、data三个字段。成功返回Result.success(data)失败抛异常后在全局异常处理器里统一返回Result.error(code, message)。不要在Controller里到处try-catch用RestControllerAdvice做全局异常处理代码会整洁非常多这个也值得在答辩里提。核心接口清单大概长这样用户模块注册、登录、登出、获取当前用户信息。场馆模块场馆分页列表、场馆详情含场地列表。预约模块查询某场地某天的空闲时间片、提交预约、取消预约、我的预约分页列表、支付模拟接口。管理端场馆增删改查、场地增删改查、预约列表按状态筛选、预约状态处理、公告管理。接口路径用REST风格比如GET /api/venue/list、POST /api/reservation、PUT /api/reservation/{id}/cancel。注意所有需要登录的接口都要经过拦截器校验前端页面跳转不到的接口也要防一手这是安全习惯。4.3 前端页面实现思路前端用Thymeleaf模板首页做好看一点印象分很关键。推荐的页面清单登录页、注册页、场馆列表页、场馆详情页带场地和时间片选择、订单确认页、支付页、我的预约页、个人中心、管理端布局页、场馆管理页、场地管理页、预约管理页、数据概览页。时间片选择是整个前端最核心的交互。我的做法是页面加载时先用Ajax请求后端接口拿到某场地某日期的时间片列表用一个表格或者宫格渲染。空闲的显示为可点击状态被占用的置灰不可点。用户点击时间片后下方汇总显示总价然后点击“提交预约”跳转订单确认页。样式直接用Bootstrap不自己写复杂CSS。Bootstrap的栅格系统做卡片式列表很方便数据概览页用简单统计卡片堆出总用户数、今日预约数、今日营收即可。4.4 演示数据与联调测试项目做完之后最重要的事情就是造一部像样的演示数据。空数据库点开全是没有记录的页面给评委的印象非常差。我一般会写一个DataInitializer类在项目启动时检查数据量如果为空就自动插入4个场馆、每个场馆3-5个场地、今天和未来三天的时间片数据、两个普通用户加一个管理员、若干条历史预约记录。时间片数据怎么生成写一个定时任务每天晚上凌晨把未来三天的未生成时间片补上。这个逻辑看起来小但实际能省很多事否则你手动往数据库里插几百条记录得累死。联调测试我习惯用Postman先测一遍所有接口注册、登录、场馆列表、提交预约、重复提交、取消预约、支付、管理员处理把能想到的正常流程和异常流程都跑一遍。然后不用Postman直接从页面过一遍完整流程不同浏览器的兼容情况也确认一下。5. 常见问题与排查技巧实录5.1 高频报错与解决办法这个项目里大家最常遇到的报错基本集中在几个地方我先按经验排个优先级。第一个是密码或用户名登录失败。排查方向很清晰先看数据库里有没有这条用户记录再看密码比对逻辑是明文还是加密后比对。很多同学注册时加密登录时忘了解密或者比对方式不一致就会一直登录不上。密码校验只推荐一种做法注册时MD5可加盐登录时对输入密码做同样的MD5计算后和数据库比对。第二个是时间格式化问题。LocalDateTime类型默认序列化出来是一长串数组前端显示极其难看。解决办法是加jackson配置全局指定日期格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8同时在前端使用Thymeleaf展示时用#temporals格式化日期。第三个是Thymeleaf页面加载报错常见的是“Error resolving template”。这个一般是模板路径不对Spring Boot默认去src/main/resources/templates/下找模板返回页面时Controller里写的字符串名字要和模板文件名匹配。用了RestController又返回字符串会被当作接口数据返回而不是页面跳转这也是新手常犯的错误——页面跳转要用Controller接口用RestController。第四个是高并发下重复预约。前面讲了InnoDB下先查后插会出问题。如果你用我推荐的条件更新写法基本能挡住如果还出问题检查事务隔离级别以及更新语句受影响行数的判断逻辑。第五个是跨域问题。如果你选了前后端分离前端Vue访问后端接口时会遇到CORS报错。解决方式是在后端写一个CorsFilter配置类允许所有来源访问或者更精细地配置允许的来源。如果不想折腾就回到Thymeleaf方案从根上避免了跨域。5.2 答辩被追问的技术点清单我整理过一份高频答辩问题清单基本覆盖这个题目的所有死角为什么选Spring Boot回答思路相比传统SSH/SSMSpring Boot提供自动配置和起步依赖开发者不需要配置繁琐的XML就能快速搭建独立可运行的Spring应用内嵌Tomcat容器让部署也更简单。MyBatis-Plus用了哪些特性回答思路通用Mapper自动实现单表CRUD条件构造器LambdaQueryWrapper避免了拼接SQL的繁琐分页插件实现物理分页。同样要会解释MyBatis-Plus和原生MyBatis的区别。怎么防止场地被重复预约这是核心中的核心。回答思路数据库层通过时间片唯一索引保证同一场地同一时间只有一个有效预约再在应用层用条件更新判断受影响行数双保险。还能补充一句“如果后续并发量增大可以引入Redis分布式锁”。预约状态是怎么流转的把0到4的流转路径完整背一遍说明哪些动作触发哪些状态变化以及超时取消的定时任务逻辑。数据库表为什么这么设计回答思路把场馆和场地拆开避免冗余预约表冗余订单金额省去Join时间字段拆成日期和起止时间方便统计和冲突判重时间片表用空间换简化逻辑。如果用户下单后不支付怎么办回答思路定时任务扫描待支付订单超过设定时间自动取消并释放时间片。系统的安全性怎么保证回答思路密码加密存储、登录拦截器、后端参数校验、全局异常处理。每个问题都要做到脱稿能讲出来不要背书面语言用自己的话把逻辑说顺。你讲得清楚评委就不追问你眼神躲闪他反而越问越深。6. 一些经验之谈带过的学生里做完这个题目的不下几十个。我的体会是真正拉开分差的不是代码量而是对业务规则的理解。同样是预约系统有的人做完只是换了皮的CRUD有的人讲冲突检测、状态机、并发控制讲得头头是道这就是高分和及格分的区别。给正在做的同学三个具体建议。第一先把数据库表和状态流转想清楚再写代码我见过太多人表结构改了四五版后面代码跟着推翻重来。第二控制项目规模不要贪多贪全——场馆评论、积分系统、会员等级这些功能选题里没要求就别加把核心链路打磨好比多几个鸡肋功能有价值得多。第三给自己留至少一周的缓冲时间用来写文档、录演示视频、准备答辩PPT别把时间卡死在写代码上。最后分享一个小技巧答辩前自己完整走一遍用户流程从注册登录到下单支付再到管理员后台管理边点边自言自语解释每一步的实现逻辑。这个方法很土但真的有效你越熟练现场就越自信。加油把这段路走完你的Java Web能力会有一个实实在在的跃升。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号