ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于Python+Vue的母婴商城毕业设计系统实现与部署详解

基于Python+Vue的母婴商城毕业设计系统实现与部署详解 每年到了三四月份总有学弟学妹来找我看毕业设计问得最多的就是“学长有没有一套完整的、能直接跑起来的系统源码”。说实话网上资源确实多但能真正让你搞懂原理、能通过答辩、还能说得清每一行代码为什么这么写的少之又少。今天我就把之前指导过的一个“基于PythonVue的母婴商城管理系统”完整拆开来讲从技术选型思路、数据库设计、前后端核心实现到环境配置和运行步骤全部过一遍。这个项目我实测跑通过源码结构清晰非常适合计算机科学与技术专业的大四学生拿来做毕业设计或者作为后端开发入门的练手项目。为什么选母婴商城这个方向原因很简单电商系统是经典业务模型涵盖用户、商品、购物车、订单、支付等多个核心模块业务逻辑完整度高。而母婴商品的特征明显比如年龄段分类、安全等级、适用人群标签等这些都可以在字段设计上体现出来比做那种空泛的“图书管理”要有说服力得多。技术栈上Python做后端开发效率高Vue做前后端分离的前端体验好这两个组合刚好覆盖了面试官最爱问的RESTful API、跨域、状态管理、路由守卫这些知识点。1. 项目整体设计与技术选型思路1.1 技术栈选型为什么是Python Vue 而不是别的组合在给毕业设计做技术选型时我一直强调一个原则不要追新要追稳。很多同学一上来就问“学长用Spring Boot行不行”“用React行不行”我的回答是行但你得先想清楚你能不能在规定时间内把它跑通并讲明白。Python这边Django和Flask是最常见的两个选择。母婴商城这种业务相对完整的项目我更推荐Django因为它自带Admin后台、ORM、认证体系和迁移工具像用户权限管理、数据库建表这些琐碎的活儿能省掉一大半。有些同学觉得Django太重了想用Flask体现自己的掌控力但毕业设计的核心是“完整能用你能讲清楚”而不是“框架特别轻量”。Django的ORM写起来非常直观比如查“所有价格在100以上的奶粉”就是一条Product.objects.filter(category__name奶粉, price__gt100)从数据库到Python对象的映射几乎是零成本理解。前端这边Vue在国内的生态成熟度远超其他框架。Element UIVue 2或Element PlusVue 3组件库提供了现成的表格、表单、弹窗、分页组件做后台管理界面就像是搭乐高。而且Vue的教程数量多、社区答疑快遇到问题一搜就有答案这对毕设周期紧的同学来说是巨大的优势。1.2 前后端分离架构的核心思考选择前后端分离架构不是因为它“流行”而是它有几个实打实的好处。第一开发可以并行——你不需要等后端接口写完才能写前端页面只要提前约定好接口返回的JSON结构两边同时开工。第二部署灵活——后端用Django跑在8000端口前端用Vue开发服务器跑在8080端口开发时通过代理转发来解决联调问题这个过程中你自然会理解什么是跨域、什么是代理、什么是中间件。第三答辩加分——当老师问你“为什么前后端要分离”时你可以从“前后端关注点分离、团队协作效率、部署扩展性”三个角度回答这种深度思考是非常加分的。整个项目的前后端交互逻辑是这样的Vue页面通过axios发起HTTP请求到Django后端的RESTful APIDjango接收请求后通过ORM操作MySQL数据库处理完业务逻辑后返回统一的JSON格式数据。整个过程是无状态的后端不记录用户登录状态而是通过JWTJSON Web Token来验证用户身份。这个设计在答辩时也是一个很好的亮点。2. 数据库设计与核心功能模块拆解2.1 六张核心表的字段设计思路母婴商城的数据库设计是整个系统的地基地基不牢后面写多少代码都是白搭。我用Django的ORM模型来定义数据表迁移时会自动在MySQL中建表不需要手写SQL。下面是我实际项目中用的核心表结构你可以直接参考用户表User继承Django自带的AbstractUser额外增加phone手机号、avatar头像、gender性别、birth_date宝宝的出生日期用于推荐适龄商品。为什么要加birth_date这是母婴商城的业务特色不同月龄的宝宝需要不同的商品这个字段在做个性化推荐时会非常有用。商品分类表Category字段包括name分类名、parent父级分类用自关联实现二级分类、sort_order排序权重。母婴商品通常是二级分类比如“奶粉”下面分“1段”“2段”“3段”“纸尿裤”下面分“NB码”“S码”“M码”自关联一张表就能搞定不需要为每个层级建一张表。商品表Product字段包括name商品名、category外键关联分类表、price价格用DecimalField而不是FloatField避免精度问题、stock库存、sales销量、image主图URL、detail富文本详情、is_active上下架状态、created_at创建时间。这里有个细节价格一定要用DecimalField(max_digits10, decimal_places2)用Float的话会出现 0.10.2!0.3 这种诡异问题答辩时如果被问到精度问题答不上来会很尴尬。购物车表Cart字段包括user外键用户、product外键商品、quantity数量、selected是否勾选。购物车表不用存商品快照因为购物车是临时数据用户随时可能改数量或删除。但订单里的商品信息必须存快照因为商品价格会变。订单表Order字段包括order_no订单编号用时间戳随机数生成、user外键用户、total_amount总金额、status订单状态待付款/已付款/已发货/已完成/已取消、address收货地址快照、created_at。订单明细表OrderItem字段包括order外键订单、product_name商品名快照、product_image商品图快照、price成交单价快照、quantity数量、subtotal小计金额。注意订单表和订单明细表为什么要拆成两张表因为一个订单包含多个商品如果不拆表就只能把多个商品塞到一个字段里比如用逗号拼接查询时根本没法分析数据。拆开后一张表负责订单整体信息一张表负责订单里的每个商品通过外键关联。这就是数据库设计中的“范式化”答辩时老师很容易问到这个点。2.2 母婴商城的业务特色如何体现在设计中做完基础表之后就要考虑母婴商城和其他电商的区别了。我在这套系统里加了两个特色维度都是答辩时的加分项。第一个是适龄推荐。通过用户在User表里存的宝宝出生日期后端可以计算出宝宝当前月龄在首页接口中按“0-6个月”“6-12个月”“1-3岁”的区间过滤商品。实现方式是在商品表加一个suitable_age字段存的是JSON格式比如 {min: 6, max: 12}查询时用ORM的过滤就能筛出合适商品。这个功能实现成本不高但能明显体现出“你做的是母婴商城而不是随便套了一个电商模板”。第二个是安全属性标签。母婴用品的家长最在意什么安全。所以我在商品表里设计了is_organic有机认证、is_imported进口商品、safety_level安全等级A/B/C这几个布尔和选择字段。商品列表中可以通过标签筛选商品详情页会醒目地展示这些标识。从产品角度讲这符合母婴用户的购买决策心理从技术角度讲这只是几个字段一个筛选接口的事投入产出比极高。2.3 订单状态机的流转逻辑订单系统的核心不是“存数据”而是“状态流转”。我用了最简单也最清晰的方案用一个整数字段表示订单状态0代表待付款、1代表已付款、2代表已发货、3代表已完成、4代表已取消。前端根据不同的状态展示不同的操作按钮——待付款显示“去支付”和“取消订单”已付款显示“申请退款”已发货显示“确认收货”。后端接口要做的是状态校验比如只有状态为0的订单才能执行支付操作只有状态为2的订单才能确认收货。我在Django的视图函数里先查订单再判断状态顺序不能反。如果你用Django REST Framework还可以在Serializer里做validated校验但毕业设计的话直接在视图里写 if 判断就够了反而更好讲清楚。3. 后端核心接口设计与实现细节3.1 基于Django REST Framework的接口分层项目后端我使用的是Django REST FrameworkDRF这是一个基于Django的第三方应用专门用来快速构建RESTful API。DRF的核心优势在于序列化器Serializer可以自动将Python对象转为JSON视图集ViewSet 路由器Router可以自动生成URL路由大大减少了重复代码。整个后端的目录结构是这样组织的backend/ ├── manage.py ├── requirements.txt ├── momshop/ # 项目配置目录 │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── apps/ │ ├── users/ # 用户模块 │ │ ├── models.py │ │ ├── views.py │ │ ├── serializers.py │ │ └── urls.py │ ├── goods/ # 商品模块 │ ├── trade/ # 购物车与订单模块 │ └── utils/ # 公共工具JWT、分页、响应格式模块化分应用是Django的最佳实践每个业务模块独立成文件夹互不干扰。我在utils里封装了统一的响应格式所有接口返回的数据结构都是{code: 200, data: {...}, message: success}前端拿到这个结构后统一处理不需要每个接口单独判断。虽然多写了一点代码但会让整个项目显得非常规范。3.2 用户认证JWT 的完整接入流程用户认证我选了JWT而不是Django自带的Session。原因有两点一是前后端分离架构下Session需要额外处理跨域Cookie的问题而JWT是无状态的前端把Token存在localStorage里每次请求在header里带上Authorization: Bearer token即可二是JWT的过期机制非常清晰Token里携带了用户ID和过期时间后端只需验证签名就能确定用户身份不需要查数据库。Django中接入JWT我用的是djangorestframework-simplejwt这个库。配置非常简单在settings.py里加一段REST_FRAMEWORK { DEFAULT_AUTHENTICATION_CLASSES: [ rest_framework_simplejwt.authentication.JWTAuthentication, ], DEFAULT_PERMISSION_CLASSES: [ rest_framework.permissions.IsAuthenticated, ], } import datetime SIMPLE_JWT { ACCESS_TOKEN_LIFETIME: datetime.timedelta(days7), REFRESH_TOKEN_LIFETIME: datetime.timedelta(days30), }登录接口在DRF里甚至不需要自己写视图直接用SimpleJWT自带的TokenObtainPairView就能返回access和refresh两个Token。但为了和前端配合得更顺畅我通常会重写这个视图让它在返回Token的同时把用户的基本信息用户名、头像、宝宝生日等也一并返回省得前端再调一次用户信息接口。3.3 首页和商品列表的分页与筛选商品列表接口是高频访问接口需要注意两个问题性能和筛选维度。性能方面我使用DRF的分页类每页返回12条商品数据前端滚动加载时传入page参数。DRF的分页响应格式默认是{count: 总数, next: 下一页链接, previous: 上一页链接, results: 数据列表}前端配合Element UI的el-pagination组件几乎可以无缝对接。筛选维度包括关键词搜索、分类筛选、价格区间、排序方式。我在视图里用request.query_params逐个获取参数并拼接到查询集上def get_queryset(self): queryset Product.objects.filter(is_activeTrue) keyword self.request.query_params.get(keyword) category_id self.request.query_params.get(category_id) min_price self.request.query_params.get(min_price) max_price self.request.query_params.get(max_price) ordering self.request.query_params.get(ordering, default) if keyword: queryset queryset.filter(name__icontainskeyword) if category_id: queryset queryset.filter(category_idcategory_id) if min_price: queryset queryset.filter(price__gtemin_price) if max_price: queryset queryset.filter(price__ltemax_price) if ordering sales: queryset queryset.order_by(-sales) elif ordering price_asc: queryset queryset.order_by(price) elif ordering price_desc: queryset queryset.order_by(-price) return queryset这段代码的每一个if都有对应的前端交互。比如价格筛选前端是两个输入框一个“确定”按钮排序方式是点击下拉菜单切换ordering参数。你把这些逻辑搞清楚了答辩时被问到“筛选功能怎么做”就可以直接说“通过查询参数动态拼接QuerySet”面试官一听就明白你是真做过而不是抄的。3.4 购物车与订单的联动实现购物车和订单的联动是电商业务的核心流程也是技术上最容易出Bug的地方。我的实现思路是前端在商品详情页点击“加入购物车”携带product_id和quantity调用POST /api/cart/。后端判断商品是否已在购物车中如果已存在则累加数量不存在则新增记录。用户在购物车页面勾选商品后点击“去结算”前端把选中的购物车记录ID列表传给后端。后端POST /api/orders/接收购物车ID列表、收货地址ID先锁定购物车记录并校验库存计算总金额创建订单和订单明细最后清空对应的购物车记录。这里有一个关键点创建订单和扣减库存必须放在同一个事务里。如果先创建订单再扣库存万一扣库存失败就会产生“订单有了但没扣库存”的数据不一致问题。Django里用transaction.atomic()装饰器就能解决from django.db import transaction transaction.atomic def create_order(request): # 1. 校验参数 # 2. 查询购物车记录 # 3. 循环检查库存 # 4. 创建订单和明细 # 5. 扣减库存product.stock - quantity # 6. 清空购物车 pass事务处理这块我在答辩时被老师重点追问过——为什么需要事务原因是并发场景下如果两个用户同时买最后一个库存商品不加事务就可能出现超卖。虽然毕设里没有真正的高并发但在代码中体现这个意识评委的好感度会明显提升。4. 前端Vue项目的架构与页面实现4.1 Vue项目目录结构与路由设计前端这边我用的是Vue 2 Vue Router 3 Vuex 3 Element UI的组合。为什么不直接上Vue 3因为Element UI目前最成熟的版本还是配合Vue 2而且能找到的教程和踩坑记录最多。如果你对自己的前端水平有信心也可以选择Vue 3 Element Plus Pinia但那是另一个故事了为了稳妥我已Vue 2作为示例。前端目录结构frontend/ ├── public/ │ └── index.html ├── src/ │ ├── main.js # 入口文件注册Vue实例 │ ├── App.vue # 根组件 │ ├── router/ │ │ └── index.js # 路由配置 │ ├── store/ │ │ └── index.js # Vuex状态管理 │ ├── api/ # 封装axios请求 │ │ ├── request.js # axios实例 拦截器 │ │ ├── product.js # 商品相关接口 │ │ ├── cart.js # 购物车相关接口 │ │ └── order.js # 订单相关接口 │ ├── views/ # 页面组件 │ │ ├── Home.vue │ │ ├── ProductList.vue │ │ ├── ProductDetail.vue │ │ ├── Cart.vue │ │ ├── Checkout.vue │ │ ├── OrderList.vue │ │ ├── Login.vue │ │ ├── Register.vue │ │ └── admin/ │ │ ├── Dashboard.vue │ │ ├── ProductManage.vue │ │ ├── OrderManage.vue │ │ └── UserManage.vue │ ├── components/ # 公共组件 │ └── utils/ └── package.json路由设计分为两块用户端和管理端。用户端路由包括首页、商品列表、商品详情、购物车、订单、登录注册管理端路由包括数据概览、商品管理、订单管理、用户管理。在路由配置中我用了路由守卫来实现登录校验和权限控制router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path.startsWith(/admin) !token) { next(/login) } else if (to.path /login token) { next(/) } else { next() } })这段代码很简单但它是前端的核心安全防线。在没有路由守卫的情况下用户直接访问/admin/product也能看到后台页面虽然拿不到数据但体验上就不完整。有了守卫后未登录的用户会被强制弹回登录页这种细节在演示时很加分。4.2 基于axios的请求封装与拦截器前端所有接口请求我都统一封装在api/request.js里而不是每个页面直接调axios。这样做最大的好处是当接口地址或公共参数发生变化时只改一个文件就行。具体实现是用axios创建实例设置基础URL为/api然后在请求拦截器里给每个请求带上Tokenimport axios from axios import { Message } from element-ui const service axios.create({ baseURL: /api, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { Message.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) } return res.data }, error { if (error.response error.response.status 401) { localStorage.removeItem(token) window.location.href /login } Message.error(error.message || 网络异常) return Promise.reject(error) } ) export default service这段代码里有几个细节值得注意。第一响应拦截器返回的是res.data而非res这样业务代码里直接productList.value await getProductList()就能拿到数据不需要每页都写.data.data这种重复嵌套。第二对401状态的统一处理Token过期时自动清空并跳回登录页这是很多毕设项目容易忽略的点。4.3 前端核心页面实现首页做了两个模块顶部的分类导航和下面的商品推荐流。分类导航的数据来源是接口GET /api/category/返回一级分类列表每个一级分类下面挂二级分类。商品推荐流则是通过商品接口的is_recommendtrue参数来过滤展示为卡片列表。商品详情页是交互最多的地方。左侧是商品图片右侧是价格、库存、销量、适龄标签和数量选择器。点击“加入购物车”按钮调用购物车接口同时弹出成功提示。我在图片展示上用了Element UI的el-carousel轮播组件支持多图切换视觉效果比固定一张图好很多。购物车页的核心是“编辑模式”和“结算模式”的切换。编辑模式下可以修改数量、删除商品结算模式下勾选商品并展示总价。Vue的computed属性非常适合算总价——只要购物车列表是响应式的总价就会自动更新不需要手动刷新。这是Vue和原生JS比最舒服的一点。订单结算页需要用户选择收货地址并确认商品清单。我预留了地址管理的接口和前端页面但因为篇幅限制在MVP版本里先用了默认地址。如果你想扩展加一个“地址管理”模块非常快就是一张address表加增删改查接口的事。管理端页面用Element UI的el-container做侧边栏顶栏的布局。商品管理页面有表格展示所有商品支持搜索、新增、编辑、上架下架操作。通常这一步会直接调用同一个商品接口只是路径和方法不同。5. 从零到一完整环境配置与运行步骤5.1 本地开发环境的前置准备在跑项目之前需要确保你的电脑已经装好了以下环境。每一步我都会说明“为什么需要”和“怎么验证装好了”。Python 3.8项目后端是基于Python开发的推荐使用3.8~3.10版本不要用最新的3.12有些依赖包可能还没有兼容。安装完后在终端输入python --version能正常输出版本号就说明没问题。Windows用户注意勾选安装器上的“Add Python to PATH”选项否则后面在终端敲python会提示找不到命令。MySQL 5.7或8.0数据库使用MySQL。安装MySQL的教程网上有很多这里提醒两点一是记住你的root密码后续配置数据库连接要用二是确保MySQL服务已经启动Windows可以通过“服务”管理器查看macOS可以用brew services start mysql。Node.js 14前端运行需要Node环境npm是Node自带的包管理工具。安装完成后终端输入node -v和npm -v两个都能正常输出版本号即可。开发工具后端推荐PyCharm或VS CodePython插件前端推荐VS CodeVetur插件。如果你不是重度IDE用户直接全程用VS Code就够。5.2 后端运行的完整步骤后端启动步骤如下第一步创建虚拟环境并激活。我强烈建议用虚拟环境每个项目一套独立的Python依赖不会互相污染。在backend目录下执行python -m venv venvWindows下激活虚拟环境venv\Scripts\activatemacOS/Linux下激活虚拟环境source venv/bin/activate激活成功后终端最前面会多一个(venv)前缀说明已经进入虚拟环境。第二步安装项目依赖。项目根目录的requirements.txt文件里列出了所有第三方库直接执行pip install -r requirements.txt主要的依赖包括Django、djangorestframework、djangorestframework-simplejwt、django-cors-headers、PyMySQL、Pillow。Pillow是处理图片上传的库如果没有它商品图片上传功能会报错。第三步配置数据库连接。在backend/momshop/settings.py中找到DATABASES配置修改为你的MySQL账号密码和数据库名DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: momshop, USER: root, PASSWORD: 你的数据库密码, HOST: 127.0.0.1, PORT: 3306, } }第四步生成数据库表并创建管理员账号。先在MySQL里手动创建数据库CREATE DATABASE momshop DEFAULT CHARACTER SET utf8mb4;然后在终端执行python manage.py makemigrations python manage.py migrate python manage.py createsuperusermakemigrations会根据models.py生成迁移脚本migrate把迁移脚本应用到数据库createsuperuser创建管理员账号用于登录Django Admin后台。第五步启动后端服务python manage.py runserver看到 “Starting development server at http://127.0.0.1:8000/” 就说明后端跑起来了。这时在浏览器访问 http://127.0.0.1:8000/admin/ 可以用管理员账号登录Django自带的后台直接在这个后台里手动添加商品分类和商品数据相当于一个简化版的后台管理。5.3 前端运行的完整步骤前端启动步骤如下第一步安装依赖。在frontend目录下执行npm installnpm install会读取 package.json 里的依赖列表并下载安装到 node_modules 文件夹里。因为依赖包数量较多这一步可能要花几分钟。如果速度极慢可以设置npm为国内镜像源npm config set registry https://registry.npmmirror.com第二步配置后端接口代理。在vue.config.js或vite.config.js取决于你用的脚手架里配置devServer的代理把前端的/api请求转发到后端的8000端口解决开发环境下的跨域问题module.exports { devServer: { port: 8080, proxy: { /api: { target: http://127.0.0.1:8000, changeOrigin: true } } } }这个代理的原理是你前端代码里请求的地址是/api/product/list浏览器看到的请求地址还是 8080 端口但devServer会在服务端把这个请求转发到 8000 端口的Django服务。这样浏览器的同源策略就不会拦截因为“表面上”所有请求都发给了同一个8080端口。第三步启动前端开发服务器npm run serve看到 “App running at: http://localhost:8080/” 说明前端启动成功。浏览器访问 http://localhost:8080 即可看到商城首页。5.4 数据初始化的快捷方案为了让系统在演示时有商品可看我准备了两种数据初始化方式。第一种是用Django的 fixture 机制在终端执行python manage.py loaddata initial_data.jsoninitial_data.json里定义好了分类数据和商品数据执行后数据库会自动填充。第二种是直接在Django Admin后台手动添加操作逻辑和普通后台一样。我强烈建议你掌握第二种方式因为答辩时老师经常问“你们后台是怎么管理的”你能现场登录Admin页面演示添加商品说服力会强很多。如果你想让首页商品图更真实可以找一些母婴商品的免费图库图片把URL填到商品的image字段里或者通过Admin后台直接上传图片文件效果会更好。6. 运行时常见问题与排查技巧实录6.1 常见运行问题速查表我在帮学弟学妹调试这个项目时整理了一份高频问题清单。你在跑的过程中如果遇到问题先按这个表逐一排查问题现象可能原因解决方法启动后端报ModuleNotFoundError: No module named pymysql依赖没装全执行pip install -r requirements.txt迁移时报Access denied for user rootlocalhostMySQL密码错误或权限不足检查settings.py中的密码和账号权限迁移时报Cant connect to MySQL serverMySQL服务未启动启动MySQL服务Windows在服务管理器启动macOS用brew services start mysql前端npm run serve报Error: Cannot find module ../lib/utils/PM2npm缓存损坏或node_modules异常删除node_modules文件夹后重新npm install前端页面能打开但接口报Network Error代理未配置或后端未启动确认后端运行在8000端口检查vue.config.js代理配置登录接口返回401 UnauthorizedToken缺失或过期清空localStorage重新登录获取新Token商品图片不显示图片URL是外链但未拼接域名在Django的settings.py中配置MEDIA_URL和STATIC_URL注册接口提示验证码错误未实现验证码但前端校验了前端注释掉验证码校验逻辑或后端增加验证码接口6.2 踩过最深的坑数据库编码与中文乱码开发过程中最让我头疼的问题是MySQL的编码设置。默认情况下MySQL创建数据库的排序规则可能是latin1_swedish_ci插入中文数据时会出现乱码或者报错Incorrect string value: \xE5\xB9\xB4...。解决办法是在创建数据库时强制指定utf8mb4编码CREATE DATABASE momshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;如果已经建好了数据库也可以通过修改数据库的默认编码来修复ALTER DATABASE momshop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;另外Django连接MySQL时也要在settings.py中设置编码OPTIONS {charset: utf8mb4}加了这行配置读取和写入中文就不会出问题了。utf8mb4和utf8的区别在于utf8mb4能完整支持四字节的emoji字符比如商品名称里带一个表情符号用utf8mb4就能正常存储。现在是移动互联网时代用户输入表情是常态所以推荐统一用utf8mb4。6.3 跨域问题的两种解决方式前端跑在8080后端跑在8000两者端口不同浏览器就会报跨域错误。除了我在前面讲的devServer代理方案还有一种是后端直接使用django-cors-headers库来允许跨域请求。具体做法是安装库在settings.py的INSTALLED_APPS中加入corsheaders在MIDDLEWARE中加入corsheaders.middleware.CorsMiddleware然后设置CORS_ALLOW_ALL_ORIGINS True开发阶段这样设置是没问题的但如果部署到生产环境应该只允许指定的域名访问否则任何人都能跨域调用你的接口存在安全隐患。我一般开发时用代理方案因为更符合生产环境的前后端同域部署模式只在需要给外部演示时临时开启CORS。两种方案都掌握面试时被问到“跨域怎么解决”就能答出两套方案。6.4 前后端接口联调的最优顺序我见过很多同学把前端页面全部写完才发现接口参数对不上然后改起来非常痛苦。正确做法是按模块联调一个模块通了再做下一个。推荐的顺序是先调通用户模块注册、登录、获取用户信息这个模块通了JWT认证链路就验证过了后面所有带Token的请求都能正常发起。再调通商品模块商品列表、分类筛选、商品详情前端的首页和列表页就能展示真实数据。接着是购物车模块因为它的业务依赖用户登录状态和商品数据。最后是订单模块它依赖前面的所有模块。按这个顺序联调每次只需要面对一个小问题域排查难度大大降低。前端API文件我也按模块拆分每个模块一个文件不要所有接口塞在一个文件里。我一开始图省事把所有接口写在api/index.js里后来项目膨胀到几十个接口后每次改动都要全局搜索定位效率极低重构后才舒服很多。7. 写在最后这套源码还能怎么扩展母婴商城管理系统做到这里已经是一个非常完整的毕业设计项目了。但如果你想让它在答辩时有更多亮点或者往简历上写的时候更有含金量我建议在这个基础版本上做下面几个方向的扩展接入支付宝沙箱支付。官方沙箱环境不需要企业资质用个人账号就能申请。在结算流程中接入真实的支付页面对跳转体验感会瞬间提升一个档次。技术上就是在后端增加一个alipay应用前端在确认订单后调用后端生成支付链接前端跳转到沙箱页面完成“支付”后端通过回调接口更新订单状态。这个功能能体现出你对支付流程的理解是加分项。增加Redis缓存。把首页的商品推荐数据在Redis中缓存10分钟减少数据库压力。虽然毕设访问量不大不加缓存也完全没问题但“我考虑过缓存设计”这个思路本身就能体现你对系统性能的思考。增加简单的销量统计报表。管理端用ECharts做一个柱状图按周展示销量前10的商品。数据源可以从订单明细表中聚合查询ECharts非常容易集成到Vue里。这个功能做好了管理的概念就完整了。部署到云服务器。如果有预算可以在阿里云或腾讯云买一台最便宜的轻量服务器把前后端分别部署上去。前端构建后交给Nginx托管后端用GunicornSupervisor跑起来。部署完成的那一刻你的简历上就可以写“独立完成系统设计、开发与部署上线”了这话是很有分量的。我在实际带项目的过程中最深的一点体会是毕业设计的技术难度其实不高真正拉开差距的是你能不能把自己做的每一步都讲明白。这套系统的每一行代码我都能解释为什么这么写每一个表字段都知道它的业务含义这才是你的核心竞争力。希望这篇拆解能帮你把这个项目跑通、吃透顺利通过答辩。
返回列表