新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于SpringBoot+Vue的摄影预约系统的设计与实现

发布时间:2026/9/30 2:28:02来源:尧图网络
基于SpringBoot+Vue的摄影预约系统的设计与实现
温馨提示本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片一、 项目背景与意义随着生活水平的提高和社交媒体的普及人们对个性化、高品质的摄影服务需求日益增长。传统的摄影预约方式如电话、微信沟通存在信息记录易错、流程不透明、时间安排冲突、客户与摄影师沟通成本高等痛点。因此开发一个线上摄影预约系统将预约流程标准化、数字化具有重要的现实意义。项目意义提升用户体验客户可以随时随地在线浏览摄影师作品、套餐详情并自主选择时间完成预约流程清晰便捷。提高商家效率系统自动化处理预约、排期、提醒等环节减少人工操作失误和沟通成本提升工作室运营效率。优化资源管理摄影师、影棚、服装道具等资源可以通过系统进行统一管理和可视化调度避免资源冲突。数据驱动决策系统积累的预约、客户、销售数据可用于分析业务趋势辅助商家进行营销策略和套餐优化。技术实践价值本项目采用前后端分离的流行架构是学习与整合 Spring Boot、Vue.js、MySQL 等主流技术的典型实践案例。二、 技术栈选型本项目采用前后端分离架构后端提供 RESTful API前端负责页面展示与用户交互。2.1 后端技术栈 (Spring Boot)核心框架Spring Boot 2.xWeb 框架Spring MVC数据持久层MyBatis-Plus (简化 CRUD 操作)数据库MySQL 8.0数据库连接池HikariCP权限认证Spring Security JWT (JSON Web Token)API 文档Swagger2 / Knife4j项目构建Maven其他工具Lombok (简化实体类) Hutool (工具包)2.2 前端技术栈 (Vue.js)核心框架Vue 3 (Composition API)构建工具Vite路由Vue Router 4状态管理PiniaUI 组件库Element PlusHTTP 客户端AxiosCSS 预处理器Sass/SCSS2.3 开发与部署版本控制Git后端部署可打包为 Jar 包使用 Docker 容器化部署或直接运行于服务器。前端部署使用 Nginx 进行静态资源托管。三、 系统核心功能模块设计系统主要分为前台用户端和后台管理端。3.1 前台用户端功能用户注册/登录支持手机号、邮箱注册JWT 认证。首页展示轮播图、推荐摄影师、热门套餐。摄影师/作品浏览分页列表、详情查看。套餐浏览与选择查看不同摄影套餐的详情、价格、样片。在线预约选择套餐、摄影师、预约日期与时间、填写个人信息及特殊要求。个人中心查看我的预约记录待支付、待拍摄、已完成、已取消、修改个人信息。订单支付集成支付宝/微信支付沙箱环境。3.2 后台管理端功能管理员登录权限控制。仪表盘显示核心数据概览今日预约数、总收入等。预约管理查看所有预约支持按状态筛选、详情查看、手动确认/取消。用户管理用户列表、信息查看、禁用/启用。摄影师管理增删改查摄影师信息、上传作品集。套餐管理摄影套餐的创建、编辑、上下架。资源管理影棚、服装道具等资源的排期与管理。系统设置基础参数配置。四、 数据库设计核心表-- 用户表 CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键, username varchar(50) DEFAULT NULL COMMENT 用户名, phone varchar(20) DEFAULT NULL COMMENT 手机号, email varchar(100) DEFAULT NULL COMMENT 邮箱, password varchar(255) DEFAULT NULL COMMENT 密码, avatar varchar(500) DEFAULT NULL COMMENT 头像, status tinyint DEFAULT 1 COMMENT 状态 1正常 0禁用, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_phone (phone), UNIQUE KEY uk_email (email) ) ENGINEInnoDB COMMENT用户表; -- 摄影师表 CREATE TABLE photographer ( id bigint NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 姓名, title varchar(100) DEFAULT NULL COMMENT 头衔/简介, avatar varchar(500) DEFAULT NULL COMMENT 头像, description text COMMENT 详细描述, score decimal(3,2) DEFAULT 5.00 COMMENT 评分, status tinyint DEFAULT 1 COMMENT 状态 1上架 0下架, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB COMMENT摄影师表; -- 摄影套餐表 CREATE TABLE package ( id bigint NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL COMMENT 套餐名称, cover_image varchar(500) DEFAULT NULL COMMENT 封面图, description text COMMENT 套餐描述, price decimal(10,2) NOT NULL COMMENT 价格, original_price decimal(10,2) DEFAULT NULL COMMENT 原价, duration int DEFAULT NULL COMMENT 预计拍摄时长(分钟), status tinyint DEFAULT 1 COMMENT 状态 1上架 0下架, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB COMMENT摄影套餐表; -- 预约订单表 (核心业务表) CREATE TABLE appointment_order ( id bigint NOT NULL AUTO_INCREMENT COMMENT 订单号, order_no varchar(32) NOT NULL COMMENT 订单编号, user_id bigint NOT NULL COMMENT 用户ID, photographer_id bigint DEFAULT NULL COMMENT 摄影师ID, package_id bigint NOT NULL COMMENT 套餐ID, appoint_date date NOT NULL COMMENT 预约日期, time_slot varchar(50) NOT NULL COMMENT 时间段, contact_name varchar(50) NOT NULL COMMENT 联系人, contact_phone varchar(20) NOT NULL COMMENT 联系电话, special_request text COMMENT 特殊要求, total_amount decimal(10,2) NOT NULL COMMENT 订单总金额, pay_status tinyint DEFAULT 0 COMMENT 支付状态 0待支付 1已支付 2已退款, order_status tinyint DEFAULT 0 COMMENT 订单状态 0待确认 1已确认 2已完成 3已取消, pay_time datetime DEFAULT NULL COMMENT 支付时间, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_user_id (user_id), KEY idx_appoint_date (appoint_date) ) ENGINEInnoDB COMMENT预约订单表;五、 核心代码实现示例5.1 后端核心代码 (Spring Boot MyBatis-Plus)1. 预约订单创建接口 (Controller)package com.photobook.appointment.controller; import com.photobook.appointment.common.R; import com.photobook.appointment.dto.AppointmentCreateDTO; import com.photobook.appointment.service.AppointmentOrderService; import com.photobook.appointment.vo.AppointmentOrderVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; RestController RequestMapping(/api/appointment) RequiredArgsConstructor Api(tags 预约订单管理) public class AppointmentOrderController { private final AppointmentOrderService appointmentOrderService; PostMapping(/create) ApiOperation(创建预约订单) public RAppointmentOrderVO createAppointment(Valid RequestBody AppointmentCreateDTO dto, RequestHeader(Authorization) String token) { // 从JWT token中解析出当前用户ID (实际项目中通过拦截器处理) Long userId JwtUtil.getUserIdFromToken(token.replace(Bearer , )); AppointmentOrderVO orderVO appointmentOrderService.createOrder(userId, dto); return R.success(orderVO); } }2. 预约订单创建服务 (Service)package com.photobook.appointment.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.photobook.appointment.dto.AppointmentCreateDTO; import com.photobook.appointment.entity.AppointmentOrder; import com.photobook.appointment.entity.Package; import com.photobook.appointment.entity.Photographer; import com.photobook.appointment.exception.BusinessException; import com.photobook.appointment.mapper.AppointmentOrderMapper; import com.photobook.appointment.mapper.PackageMapper; import com.photobook.appointment.mapper.PhotographerMapper; import com.photobook.appointment.service.AppointmentOrderService; import com.photobook.appointment.utils.OrderNoGenerator; import com.photobook.appointment.vo.AppointmentOrderVO; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; Service RequiredArgsConstructor public class AppointmentOrderServiceImpl implements AppointmentOrderService { private final AppointmentOrderMapper appointmentOrderMapper; private final PackageMapper packageMapper; private final PhotographerMapper photographerMapper; Override Transactional(rollbackFor Exception.class) public AppointmentOrderVO createOrder(Long userId, AppointmentCreateDTO dto) { // 1. 校验套餐是否存在且上架 Package pkg packageMapper.selectById(dto.getPackageId()); if (pkg null || pkg.getStatus() ! 1) { throw new BusinessException(套餐不存在或已下架); } // 2. 校验摄影师是否存在且可用 (如果指定了摄影师) if (dto.getPhotographerId() ! null) { Photographer photographer photographerMapper.selectById(dto.getPhotographerId()); if (photographer null || photographer.getStatus() ! 1) { throw new BusinessException(指定的摄影师不可用); } } // 3. 校验预约时间冲突 (简化示例检查同一天同一时间段是否已有预约) LambdaQueryWrapperAppointmentOrder conflictQuery new LambdaQueryWrapper(); conflictQuery.eq(AppointmentOrder::getAppointDate, dto.getAppointDate()) .eq(AppointmentOrder::getTimeSlot, dto.getTimeSlot()) .in(AppointmentOrder::getOrderStatus, 0, 1); // 待确认和已确认的订单 Long conflictCount appointmentOrderMapper.selectCount(conflictQuery); if (conflictCount 0) { throw new BusinessException(该时间段已被预约请选择其他时间); } // 4. 构建订单实体 AppointmentOrder order new AppointmentOrder(); order.setOrderNo(OrderNoGenerator.generate()); order.setUserId(userId); order.setPhotographerId(dto.getPhotographerId()); order.setPackageId(dto.getPackageId()); order.setAppointDate(dto.getAppointDate()); order.setTimeSlot(dto.getTimeSlot()); order.setContactName(dto.getContactName()); order.setContactPhone(dto.getContactPhone()); order.setSpecialRequest(dto.getSpecialRequest()); order.setTotalAmount(pkg.getPrice()); order.setPayStatus(0); order.setOrderStatus(0); // 5. 保存订单 appointmentOrderMapper.insert(order); // 6. 返回VO对象 (实际项目中可使用MapStruct进行转换) return convertToVO(order, pkg); } private AppointmentOrderVO convertToVO(AppointmentOrder order, Package pkg) { AppointmentOrderVO vo new AppointmentOrderVO(); // ... 属性拷贝 return vo; } }5.2 前端核心代码 (Vue 3 Element Plus)1. 预约页面组件 (Appointment.vue)template div classappointment-page el-steps :activeactiveStep finish-statussuccess el-step title选择套餐/el-step el-step title选择时间/el-step el-step title填写信息/el-step el-step title确认预约/el-step /el-steps !-- 步骤1: 选择套餐 -- div v-ifactiveStep 0 h3选择摄影套餐/h3 el-row :gutter20 el-col :span8 v-forpkg in packageList :keypkg.id el-card :class{ selected: selectedPackageId pkg.id } clickselectPackage(pkg) img :srcpkg.coverImage classpackage-cover / div stylepadding: 14px; h4{{ pkg.name }}/h4 p{{ pkg.description }}/p div classprice span classcurrent-price¥{{ pkg.price }}/span span classoriginal-price v-ifpkg.originalPrice¥{{ pkg.originalPrice }}/span /div /div /el-card /el-col /el-row el-button typeprimary clicknextStep :disabled!selectedPackageId下一步/el-button /div !-- 步骤2: 选择时间 -- div v-ifactiveStep 1 h3选择预约时间/h3 el-date-picker v-modelform.appointDate typedate placeholder选择日期 :disabled-datedisabledDate changeloadTimeSlots / el-select v-modelform.timeSlot placeholder选择时间段 el-option v-forslot in availableTimeSlots :keyslot :labelslot :valueslot / /el-select div stylemargin-top: 20px; el-button clickprevStep上一步/el-button el-button typeprimary clicknextStep :disabled!form.appointDate || !form.timeSlot下一步/el-button /div /div !-- 步骤3: 填写信息 -- div v-ifactiveStep 2 h3
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Intel X710网卡Linux性能调优实战:RSS/IRQ/NUMA黄金配置 2026/9/30 3:26:09

Intel X710网卡Linux性能调优实战:RSS/IRQ/NUMA黄金配置

简介:本资源为Intel以太网控制器X710/XXV710/XL710官方数据手册(Datasheet)PDF文档,面向网络设备开发工程师、驱动开发者、数据中心硬件架构师及Linux/Windows系统底层技术学习者,解决高性能网卡选型、硬件集成、驱动适…

阅读更多 →
华为GVRP配置与排错:注册方向、模式边界与单向传播机制 2026/9/30 3:26:09

华为GVRP配置与排错:注册方向、模式边界与单向传播机制

简介:本资源是一份面向网络工程初学者与华为设备实操学习者的GVRP动态VLAN配置实验文档,聚焦交换机间VLAN信息自动注册与管理这一核心技能。文档完整呈现四台华为交换机(S1–S4)的GVRP部署全过程,涵盖Trunk端口配置、三…

阅读更多 →
华为交换机GVRP配置实战:原理、避坑与精细化控制 2026/9/30 3:26:09

华为交换机GVRP配置实战:原理、避坑与精细化控制

简介:本资源是一份面向网络工程学习者与华为设备初学者的GVRP(GARP VLAN Registration Protocol)实验配置详解文档,聚焦动态VLAN注册与管理这一核心网络技能,解决多交换机环境下手工配置VLAN易出错、扩展性差的问题。文…

阅读更多 →
Linux进程从入门到排障:状态、通信与杀手锏一次讲清 2026/9/30 3:26:02

Linux进程从入门到排障:状态、通信与杀手锏一次讲清

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Bootstrap入门到实战:组件系统、栅格、下拉菜单与表单校验 2026/9/30 3:26:02

Bootstrap入门到实战:组件系统、栅格、下拉菜单与表单校验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Docker部署Alist配置SSL证书:从选型到自动续期全攻略 2026/9/30 3:25:56

Docker部署Alist配置SSL证书:从选型到自动续期全攻略

1. 为什么Docker里的Alist一定要配SSL证书先说个我自己的经历。很早之前我在一台小机器上用Docker跑Alist,图省事直接用http://IP:5244访问,用了大半年一直没当回事。后来有一次在外部网络环境下列表文件,浏览器直接弹了个“不安全连接”的警…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉