新闻详情

新闻详情

首页 / 资讯中心 / 详情

Python+Django+Vue构建酒店预订管理系统:从模型到前后端联调全攻略

发布时间:2026/10/1 1:17:24来源:尧图网络
Python+Django+Vue构建酒店预订管理系统:从模型到前后端联调全攻略
简介这是一份基于Python、Django与Vue.js开发的酒店预订管理系统完整源码适合毕业设计、课程设计及初学全栈开发的人群使用。平台采用B/S结构前台包含首页、客房详情、订单中心与用户中心后台覆盖总览、订单管理、客房管理、房间分类、标签、评论、用户、运营、日志及系统信息等模块功能闭环较完整。资源共391个文件压缩包约33.19MB其中jpeg/jpg/png等图片素材占多数用于页面展示与客房示例py文件为Django后端逻辑vue文件是前端组件ts/js/svg/woff等覆盖脚本、图标与字体资源目录明确分为server与web两端便于直接定位代码和二次开发。后端依赖清单requirements.txt和分步部署说明也包含在内方便在Python 3.8环境中快速启动运行。当前已有249人浏览学习适合需要完整参考实现、快速搭建酒店预订全栈项目的同学。1. 毕业设计做酒店预订管理系统为什么PythonDjangoVue这条链路值得你完整走一遍很多毕业设计的题目都会落在“XX管理系统”上但酒店预订管理系统和图书管理、学生管理有个本质区别它有真实业务状态——房间有没有被订、订单从提交到入住再到退房怎么流转、同一间房被两个人同时下单怎么办。用PythonDjangoVue来做这个题目等于把数据库建模、后端接口、前端交互、登录权限整个闭环都亲手过一遍答辩时无论老师问哪一层你都有实际代码可以讲。这篇笔记按开发顺序展开从建项目到前后端联调每段代码都标注了参数含义和失败时看什么适合正在准备毕设、或者想复现一套全栈项目练手的人。2. 搭建Django后端项目初始化、App划分与三个核心数据模型2.1 为什么毕设后端选Django而不是Flask或Node对django项目实战新手来说最容易纠结的是框架选型。酒店预订系统看着简单但订单、房型、用户之间的关联关系很典型用Django做后端的最大收益不是“写起来快”而是它把很多答辩会问的东西都封装到了明面上ORM迁移能直接看到SQL、Admin后台能直接录入数据、认证有现成的User表。你不需要为了一个登录功能去翻flask-login的文档也不用为了建表去学SQLAlchemy的配置方式。Flask确实更轻适合做几个接口的小工具但毕设要的是完整系统你还要画E-R图、写用例、做演示Django自带的这套全家桶能帮你省出至少两到三天的联调时间。Node后端比如Express也常见但对大部分非前端专业的同学来说用JavaScript写后端的排查成本反而更高不如Python顺手。选型对比如下对比项DjangoFlaskORM内置自带迁移命令需要搭配 SQLAlchemy 等第三方库管理后台自带 Admin注册模型即可用需要手写或装扩展认证与权限自带 User 模型与 Session一般要引入 flask-login适合场景管理系统、前后端分离后端小工具、纯API演示2.2 创建虚拟环境与初始化项目最小命令清单先确认本机已经按对应系统的教程装好了Python 3.10及以上版本然后在VSCode或PyCharm里打开项目目录先建虚拟环境。这个步骤最容易被人跳过但只有用了虚拟环境后面装包、换机器、打包交源码时才不会出现“我这能跑你那就报错”的局面。# 创建虚拟环境目录名就叫 venv python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS / Linux: source venv/bin/activate # 安装基础依赖Django 主框架、DRF 接口库、跨域处理组件 pip install django djangorestframework django-cors-headers # 创建项目项目名定为 hotel_project django-admin startproject hotel_project # 进入项目目录创建一个承载业务代码的 app cd hotel_project python manage.py startapp bookings # 生成迁移并执行验证环境没有问题 python manage.py makemigrations python manage.py migrate注意第一次执行makemigrations显示No changes detected是正常的因为还没有注册任何app不要以为是命令敲错了。startapp bookings中的bookings是业务模块名订单、房型这些模型都放在这个app里。如果你想把酒店管理和订单拆成两个app也可以但毕设规模下一个app足够表达清楚反而更好讲。2.3 设计三个核心模型酒店、房型、订单酒店预订的核心数据模型是三个酒店、房型、订单。酒店和房型是一对多房型和订单也是一对多用户和订单是一对多。把这三种关系建清楚E-R图基本就画完了一大半。下面是bookings/models.py的完整代码from django.db import models from django.contrib.auth.models import User class Hotel(models.Model): 酒店基本信息由管理员在后台录入前端只读展示 name models.CharField(酒店名称, max_length100) address models.CharField(地址, max_length200) city models.CharField(城市, max_length50) description models.TextField(描述, blankTrue) created_at models.DateTimeField(创建时间, auto_now_addTrue) def __str__(self): return self.name class Meta: db_table hotel class RoomType(models.Model): 房型挂在酒店下一间酒店有多个房型 hotel models.ForeignKey( Hotel, on_deletemodels.CASCADE, related_nameroom_types, # 反向查询hotel.room_types.all() verbose_name所属酒店 ) name models.CharField(房型名称, max_length50) # 大床房 / 双床房 price models.DecimalField(价格, max_digits8, decimal_places2) total_rooms models.PositiveIntegerField(房间总数, default1) remain_rooms models.PositiveIntegerField(剩余房间数, default1) def __str__(self): return f{self.hotel.name} - {self.name} class Meta: db_table room_type class Booking(models.Model): 订单status 字段用 choices 管理状态流转 STATUS_CHOICES [ (pending, 待支付), (paid, 已支付), (checked_in, 已入住), (checked_out, 已退房), (cancelled, 已取消), ] user models.ForeignKey( User, on_deletemodels.CASCADE, related_namebookings, verbose_name下单用户 ) room_type models.ForeignKey( RoomType, on_deletemodels.PROTECT, related_namebookings, verbose_name预订房型 ) check_in models.DateField(入住日期) check_out models.DateField(离店日期) status models.CharField( 订单状态, max_length20, choicesSTATUS_CHOICES, defaultpending ) create_time models.DateTimeField(下单时间, auto_now_addTrue) class Meta: db_table booking几个关键参数要理解清楚答辩会被问到。on_deletemodels.CASCADE表示酒店被删除时它下面的所有房型一并删除这是符合业务直觉的但Booking.room_type用的是PROTECT意思是只要有订单引用了某个房型这个房型就不能被直接删除否则会报ProtectedError。这是刻意做的保护防止管理员把已经有人预订的房型删掉导致数据悬空。related_name定义了反向查询的名字比如hotel.room_types.all()就能拿到这家酒店的所有房型user.bookings.all()能拿到该用户的所有订单。不写related_name时Django会默认生成hotel_set这种名字可读性差很多。auto_now_addTrue会在第一次保存时自动写入当前时间不需要手动赋值。2.4 注册App、配置中文环境并完成首次迁移模型写完要注册到settings.py的INSTALLED_APPS里Django才知道这个app存在。LANGUAGE_CODE和TIME_ZONE建议在项目一开始就改成中文和上海时区不然后面日期显示全是英文和UTC时间前端展示订单时间时会有8小时的偏差。# hotel_project/settings.py INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, rest_framework, corsheaders, bookings, ] MIDDLEWARE [ corsheaders.middleware.CorsMiddleware, django.middleware.security.SecurityMiddleware, # 其他默认中间件保持不动 ] LANGUAGE_CODE zh-hans TIME_ZONE Asia/Shanghai接着把三个模型注册到后台方便管理端录入酒店和房型数据也可以在答辩时直接在Admin后台演示数据的增删改。注册写在一个你新建后台文件里会更整洁# bookings/admin.py from django.contrib import admin from .models import Hotel, RoomType, Booking admin.register(Hotel) class HotelAdmin(admin.ModelAdmin): list_display (name, city, address) admin.register(RoomType) class RoomTypeAdmin(admin.ModelAdmin): list_display (hotel, name, price, remain_rooms) admin.register(Booking) class BookingAdmin(admin.ModelAdmin): list_display (user, room_type, status, check_in, check_out)然后执行python manage.py makemigrations和python manage.py migrate生成数据库表接着python manage.py createsuperuser创建管理员账号最后python manage.py runserver打开http://127.0.0.1:8000/admin/就能在后台看到三个模型了。这一步跑通后端骨架就是完整的可以继续接接口层。3. 用DRF把后端变成接口序列化器、视图集与JWT登录3.1 为什么用DRF而不是直接返回JsonResponse新手最容易走弯路的地方是明明装了DRF写接口时还在视图里手动queryset.values()转JSON再JsonResponse返回。这样的问题在于酒店列表要嵌套返回房型数据时你得手工写双层循环拼接数据订单列表要返回用户名、房型名时还得再查两次表。几个接口写下来全是重复的序列化代码。DRF的ModelSerializer能把模型直接转成JSON嵌套关系用几行代码就能表达还附带分页、过滤、认证这些工具。对酒店预订管理系统这种标准CRUD项目来说DRF可以少写大约一半的视图代码。核心收益不是“少敲键盘”而是接口返回的字段结构一致前端拿到的数据不容易出现“这个接口有name那个接口有hotel_name”的混乱。3.2 编写序列化器字段控制与嵌套展示在bookings/serializers.py里定义三个序列化器。这里要注意代码顺序HotelSerializer里嵌套了RoomTypeSerializer所以被嵌套的要写在前面。from rest_framework import serializers from .models import Hotel, RoomType, Booking class RoomTypeSerializer(serializers.ModelSerializer): class Meta: model RoomType fields [id, name, price, total_rooms, remain_rooms] class HotelSerializer(serializers.ModelSerializer): # 嵌套返回该酒店下的所有房型 room_types RoomTypeSerializer(manyTrue, read_onlyTrue) class Meta: model Hotel fields [id, name, address, city, description, room_types] class BookingSerializer(serializers.ModelSerializer): # 前端只需要用户id后端自动绑定房间详情嵌套展示 user serializers.PrimaryKeyRelatedField(read_onlyTrue) room_type_detail RoomTypeSerializer(sourceroom_type, read_onlyTrue) nights serializers.SerializerMethodField() class Meta: model Booking fields [id, user, room_type, room_type_detail, check_in, check_out, status, create_time, nights] def get_nights(self, obj): 入住天数前端直接用避免重复计算 return (obj.check_out - obj.check_in).daysfields里写明的字段就是接口会返回的字段没写的不会出现。注意user设成了read_onlyTrue因为用户应该从登录状态里取而不是让前端传一个user_id来伪造下单人。SerializerMethodField用来生成模型里没有但前端需要的字段get_nights里做日期加减返回两个日期相差的天数。3.3 用视图集接管增删改查并注册路由视图部分用ModelViewSet可以把list、create、retrieve、update、delete全部接管。酒店和房型主要是查询游客也能看权限放行订单涉及用户数据必须登录才能操作。perform_create是重写创建逻辑的地方在这里把当前登录用户绑定到订单上同时扣减房型剩余房间数。# bookings/views.py from rest_framework import viewsets, permissions from rest_framework.exceptions import ValidationError from .models import Hotel, RoomType, Booking from .serializers import HotelSerializer, RoomTypeSerializer, BookingSerializer class HotelViewSet(viewsets.ReadOnlyModelViewSet): 酒店和房型以查询为主游客可看 queryset Hotel.objects.all() serializer_class HotelSerializer permission_classes [permissions.AllowAny] class RoomTypeViewSet(viewsets.ReadOnlyModelViewSet): queryset RoomType.objects.select_related(hotel).all() serializer_class RoomTypeSerializer permission_classes [permissions.AllowAny] class BookingViewSet(viewsets.ModelViewSet): 订单必须登录才能操作 queryset Booking.objects.all() serializer_class BookingSerializer permission_classes [permissions.IsAuthenticated] def get_queryset(self): # 每个用户只能看到自己的订单 return self.queryset.filter(userself.request.user) def perform_create(self, serializer): # 下单时自动绑定用户同时扣减剩余房间数 room_type serializer.validated_data[room_type] if room_type.remain_rooms 0: raise ValidationError({detail: 该房型已满暂时无法预订}) serializer.save(userself.request.user) room_type.remain_rooms - 1 room_type.save(update_fields[remain_rooms])这里要留意get_queryset里按request.user过滤了订单列表否则随便登录一个用户就能看到所有人的订单——这是毕设里经常出现的越权漏洞。remain_rooms的扣减在并发场景下会有超卖风险但对毕设演示来说足够答辩时如果能主动说出这个局限并提出用事务加锁解决反而是加分项。路由注册用DRF的DefaultRouterURL前缀和视图集绑定后标准的路由规则全自动生成# bookings/urls.py from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import HotelViewSet, RoomTypeViewSet, BookingViewSet router DefaultRouter() router.register(hotels, HotelViewSet, basenamehotel) router.register(room-types, RoomTypeViewSet, basenameroom-type) router.register(bookings, BookingViewSet, basenamebooking) urlpatterns [ path(, include(router.urls)), ]3.4 登录与权限用JWT替代Session前端分离更顺手前后端分离项目里Session方案要把cookie和csrf一并处理调试起来比较麻烦。常见做法是改用JWT用户登录后拿到一个token前端存在localStorage里后续请求带上Authorization: Bearer token。Django下对应的方案是djangorestframework-simplejwt安装并配置pip install djangorestframework-simplejwt# settings.py from datetime import timedelta REST_FRAMEWORK { DEFAULT_AUTHENTICATION_CLASSES: [ rest_framework_simplejwt.authentication.JWTAuthentication, ], DEFAULT_PERMISSION_CLASSES: [ rest_framework.permissions.IsAuthenticatedOrReadOnly, ], } SIMPLE_JWT { ACCESS_TOKEN_LIFETIME: timedelta(hours12), # 演示时减少刷新次数 REFRESH_TOKEN_LIFETIME: timedelta(days7), }# hotel_project/urls.py from django.contrib import admin from django.urls import path, include from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView urlpatterns [ path(admin/, admin.site.urls), path(api/token/, TokenObtainPairView.as_view(), nametoken_obtain_pair), path(api/token/refresh/, TokenRefreshView.as_view(), nametoken_refresh), path(api/, include(bookings.urls)), ]ACCESS_TOKEN_LIFETIME默认只有5分钟对毕设演示来说太短演示过程中一半时间在重新登录观感很差。改成12小时再配合7天有效期的refresh token足够支撑两三天的演示周期。JWT的完整流程是前端用用户名密码请求/api/token/返回access和refresh两个字段access过期后用refresh去/api/token/refresh/换新。能讲清楚这套流程答辩时认证这块就站得住。4. Vue3前端对接创建项目、axios封装与跨域代理4.1 初始化Vue3项目并安装依赖vue安装及环境配置是前端部分的第一道坎。用Vite创建Vue3项目记得先装Node.js并确认node -v能输出版本号。npm create vue会有一段交互式配置建议勾选Vue RouterPinia看个人习惯这两个对酒店预订系统来说够用了。# 创建Vue3项目项目名 hotel_web npm create vuelatest hotel_web # 进入项目目录并安装基础依赖 cd hotel_web npm install # 安装axios用于请求后端接口 npm install axios # 安装Element Plus作为UI库毕设界面会整洁很多 npm install element-plus # 启动开发服务器默认端口5173 npm run devElement Plus不是必须的但对酒店预订这类管理界面来说用原生HTML排版容易显得简陋答辩演示时的视觉效果差距很大。装UI库后表格、表单、日期选择器都有现成组件后面前端代码量也能少写不少。Vite的默认端口是5173后面配置代理时要和这个端口对得上。4.2 axios实例封装统一token注入与错误拦截前端所有接口请求最好走同一个axios实例不要每个页面import axios直接用否则token注入和401处理要在每个页面重复写。下面是常见的src/api/request.js封装方式import axios from axios // 创建axios实例baseURL先指向后端根路径 const request axios.create({ baseURL: /api, // 开发环境走Vite代理不需要写完整域名 timeout: 10000, }) // 请求拦截器每次请求自动带上JWT request.interceptors.request.use(config { const token localStorage.getItem(access_token) if (token) { config.headers.Authorization Bearer ${token} } return config }) // 响应拦截器统一处理401和错误提示 request.interceptors.response.use( response response.data, error { if (error.response error.response.status 401) { localStorage.removeItem(access_token) localStorage.removeItem(refresh_token) window.location.href /login } return Promise.reject(error) } ) export default request拦截器的意义在于所有请求在发出前会被统一检查是否有token有就自动加上页面代码里完全不用关心token拼接的事。response.data直接返回业务数据调用方拿到的就是{id: 1, name: ...}这种结构。401处理很关键token过期时自动清掉并跳回登录页比每个请求里写一遍判断靠谱得多。4.3 跨域问题Vite代理和Django的CORS配置开发环境跨域是前后端分离项目最容易翻车的地方。浏览器直接访问http://127.0.0.1:8000时只要前端的地址是5173就必然触发跨域检查。常见做法是让Vite开发服务器做代理前端只请求5173Vite把/api开头的请求转发到8000端口。这样浏览器视角里所有请求都来自同源跨域问题在开发阶段基本消失。// vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { port: 5173, proxy: { /api: { target: http://127.0.0.1:8000, changeOrigin: true, }, }, }, })配置完成后把request.js里的baseURL改成/api请求/api/hotels/时Vite会转发到http://127.0.0.1:8000/api/hotels/。changeOrigin: true的作用是让后端看到的请求头来源是8000端口否则某些场景下Django会认为来路不对。如果不用代理前端直接请求完整地址那Django侧就必须配置django-cors-headers# settings.py CORS_ALLOW_ALL_ORIGINS True # 开发阶段用上线前需要收紧为具体域名这条配置只在“前端直接跨域请求8000”时才需要。用了Vite代理之后就不用开它两套方案不要同时纠结优先用代理逻辑更干净。4.4 登录页面与路由守卫从token到首页的流程登录页是前后端连通的第一站。请求/api/token/拿到token后存到localStorage然后跳转首页。这里有个坑simplejwt的登录接口接收的是username和passwordaxios默认以JSON格式提交时字段名必须一致否则会返回400。!-- src/views/LoginView.vue -- template div classlogin-box el-form :modelform label-width80px el-form-item label用户名 el-input v-modelform.username / /el-form-item el-form-item label密码 el-input v-modelform.password typepassword show-password / /el-form-item el-button typeprimary clickhandleLogin登录/el-button /el-form /div /template script setup import { ref } from vue import { useRouter } from vue-router import request from ../api/request const router useRouter() const form ref({ username: , password: }) async function handleLogin() { const data await request.post(/token/, { username: form.value.username, password: form.value.password, }) localStorage.setItem(access_token, data.access) localStorage.setItem(refresh_token, data.refresh) router.push(/) } /script路由守卫负责控制未登录用户不能进入页面。在src/router/index.js里注册beforeEach每次路由跳转前检查有没有tokenimport { createRouter, createWebHistory } from vue-router const router createRouter({ history: createWebHistory(), routes: [ { path: /, component: () import(../views/HomeView.vue) }, { path: /login, component: () import(../views/LoginView.vue) }, ], }) router.beforeEach((to) { const token localStorage.getItem(access_token) if (to.path ! /login !token) { return /login } }) export default router酒店详情页需要带参数跳转时vue路由参数的写法是把id拼在path里例如/hotel/1然后通过route.params.id取出来去请求对应酒店的详情接口。这部分逻辑不复杂但要注意动态路由的路径参数名必须与params的key一致拼错就变成404。调试前端时打开浏览器开发者工具里的vue devtools插件能直接看到每个组件的form值、route参数和localStorage中的token比到处写console.log直观得多。5. 避坑指南酒店预订系统从开发到演示的5个高频事故5.1 Django静态文件显示不了样式全丢现象前端页面能打开但引用的CSS、JS全部404页面裸奔。原因settings.py里只配置了STATIC_URL /static/但项目里实际存放静态文件的目录没有告诉Django。Django在开发环境下只会去每个app的static子目录找文件如果你把静态文件放在项目根目录下的static文件夹里不额外声明它根本不知道有这个地方。解决在settings.py里添加STATICFILES_DIRS指向项目根目录下的静态文件目录# settings.py import os STATIC_URL /static/ STATICFILES_DIRS [ os.path.join(BASE_DIR, static), ]创建目录后把CSS、JS放进去重启runserver再看。注意STATIC_URL和STATICFILES_DIRS要同时存在只配一处都会404。5.2 前端请求跨域代理配了CORS也开了还报错现象浏览器控制台报CORS policy错误或者请求返回500看Network面板发现请求地址还是http://127.0.0.1:8000。原因axios的baseURL写成了完整的后端地址比如http://127.0.0.1:8000/api这样请求根本不会走Vite的/api代理而是浏览器直接跨域访问8000。代理配置只对以/api开头的相对路径生效。解决把request.js里的baseURL改为/api确保所有请求以/api开头。然后确认vite.config.js中代理的target端口写的是Django的8000而不是前端自己的5173。如果改了配置还是不生效重启npm run devVite的代理配置修改后需要重启开发服务器才会重新加载。5.3 删除对象时被外键拦住django执行查询删除对象报ProtectedError现象在Admin后台删除一个房型时报错ProtectedError: Cannot delete some instances of model RoomType删除不掉。原因这是Booking.room_type字段上on_deletemodels.PROTECT的预期行为。设计时为了保护订单数据订单一旦引用了某个房型这个房型就不允许被删除。新手不清楚这个机制以为Django出问题了。解决按业务场景选一种处理方式。如果订单可以失去房型关联就把外键改成可空加SET_NULLroom_type models.ForeignKey( RoomType, on_deletemodels.SET_NULL, nullTrue, blankTrue, related_namebookings, )如果订单必须保留房型信息那就不允许删除改成“下架”操作更合理给房型加一个is_active布尔字段删除时改为False前端过滤显示。改完模型别忘了执行makemigrations和migrate。5.4 日期格式变成2024-03-15T08:00:00Z现象Vue页面里展示订单时间显示的是2024-03-15T08:00:00Z这种带字母的字符串用户根本看不懂。原因DRF默认的DateTimeField输出ISO 8601格式带时区后缀同时Django的TIME_ZONE没设置或者用的默认UTC导致本地时间被转换成UTC再加了Z标识。解决第一步把settings.py里的TIME_ZONE改成Asia/Shanghai第二步在REST_FRAMEWORK里统一配置时间输出格式REST_FRAMEWORK { DATETIME_FORMAT: %Y-%m-%d %H:%M:%S, }配置后接口返回的create_time会变成2024-03-15 16:00:00这样的字符串前端直接展示即可不需要再做Date解析。注意DATE_FORMAT管日期DATETIME_FORMAT管时间两个都配上最稳妥。5.5 房间图片上传显示404MEDIA_ROOT与路由缺失现象房间图片上传成功文件也能在服务器目录里看到但前端img src/media/room/xx.jpg访问404。原因settings.py里配了MEDIA_ROOT和MEDIA_URL但项目主urls.py里没有把media目录路由挂进去。开发环境下runserver不会自动处理media文件的访问需要手动加一条路由。解决在hotel_project/urls.py里追加from django.conf import settings from django.conf.urls.static import static urlpatterns [ # 已有的路径 ] static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)这样开发环境就能访问/media/下的文件。部署到云服务器后这条路由不够用要让Nginx直接托管media目录否则上传文件会全部堆积在Django进程中这是上线前要处理的事。6. 答辩演示的加分技巧接口自测、调试面板与权限进阶演示之前给自己留半分钟做接口自检。打开浏览器访问http://127.0.0.1:8000/api/hotels/DRF的可浏览API页面能看到JSON数据和表单界面这个页面本身就可以当作答辩时的“接口文档”展示。再用vue devtools确认请求头里带了Authorizationtoken没有过期这一步能排除掉大半现场翻车的可能。后端可以装一个django-debug-toolbar开发环境下每页底部会显示SQL查询条数和耗时。答辩时调到“酒店列表”页截一张图展示Django ORM把嵌套查询翻译成SQL的过程比空口讲“ORM很方便”有说服力得多。pip install django-debug-toolbar权限这块还有一个常见加分项给系统加简单的RBAC。Django自带的Group和Permission就能实现“前台只能查看和创建订单管理员才能修改房型价格”的区分不需要额外引包。django-admin后台默认的样子偏朴素如果还有时间可以试试django-unfold这类现代后台皮肤装上后整个后台界面风格焕然一新答辩演示时第一眼印象会好不少。我自己的习惯是演示前一定把“从下单到房态减少”这条完整链路用两个账号走一遍——普通用户在前端下单管理员在后端看到剩余房间数变化。这个闭环能跑通说明前后端联调、数据库外键、权限控制三个核心环节都没问题。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

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

较早相关资讯

最新相关资讯

Unity游戏开发:血量、数组与坐标的内存管理实战 2026/10/1 2:12:17

Unity游戏开发:血量、数组与坐标的内存管理实战

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

阅读更多 →
AlphaFold 蛋白结构预测完整指南:4 步从零跑通,附质量判断方法 2026/10/1 2:12:17

AlphaFold 蛋白结构预测完整指南:4 步从零跑通,附质量判断方法

AlphaFold 蛋白结构预测完整指南:4 步从零跑通,附质量判断方法 【免费下载链接】alphafold Open source code for AlphaFold 2. 项目地址: https://gitcode.com/GitHub_Trending/al/alphafold 如果你手头只有一段氨基酸序列,却想知道它…

阅读更多 →
终极指南:如何构建你的个人商业模式2.0 2026/10/1 2:12:11

终极指南:如何构建你的个人商业模式2.0

终极指南:如何构建你的个人商业模式2.0 在当今快速变化的商业环境中,一人企业方法论为你提供了一套完整的思考框架,帮助你在资源有限的情况下实现以小博大。无论你是独立开发者、内容创作者还是数字创业者,这套系统化的方法论都能…

阅读更多 →
Vue3 自动导入插件 unplugin-auto-import 完整配置与踩坑指南 2026/10/1 2:12:10

Vue3 自动导入插件 unplugin-auto-import 完整配置与踩坑指南

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

阅读更多 →
火灾烟雾人员检测数据集:从数据清洗到YOLO训练全流程 2026/10/1 2:12:10

火灾烟雾人员检测数据集:从数据清洗到YOLO训练全流程

简介:这份火灾烟雾人员检测数据集面向智能消防、安防监控与应急救援方向的算法开发者与研究人员,用于训练和评估火灾场景下的多目标检测模型。数据全部来自真实监控与航拍环境,覆盖室内外不同光照与天气条件,标注为YOLO格式&#…

阅读更多 →
MAS 激活脚本完整指南:4 种方式免费激活 Windows 和 Office 2026/10/1 2:12:09

MAS 激活脚本完整指南:4 种方式免费激活 Windows 和 Office

MAS 激活脚本完整指南:4 种方式免费激活 Windows 和 Office 【免费下载链接】Microsoft-Activation-Scripts Open-source Windows and Office activator featuring HWID, Ohook, TSforge, and Online KMS activation methods, along with advanced troubleshooting.…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

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

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