尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot+Vue全栈实战:构建智能家居销量数据分析平台

SpringBoot+Vue全栈实战:构建智能家居销量数据分析平台 做智能家居这一行的朋友应该都有体会产品线一旦铺开销量数据的统计就会变得非常痛苦。智能音箱、智能门锁、智能插座、安防摄像头每类产品都有好几个型号线上有淘宝、京东、拼多多线下有经销商和专卖店再加上一些大B集采订单渠道维度又多了一层。我前阵子跟着团队完成的jrabo系统就是为了解决这种散落原始数据的归集与分析问题——一个典型的前后端分离销量数据分析平台后端用SpringBoot MyBatis MySQL前端用Vue从数据库表设计、接口开发到页面展示和部署打包整套链路我这次一并梳理出来。如果你正在准备类似的技术项目或者想找一套可以复现的完整全栈源码做参考这篇内容应该能帮你少走不少弯路。这套系统本身不算特别复杂但胜在业务逻辑完整商品档案、订单流水、时间维度统计、产品/渠道维度聚合、前端图表联动全都走了一遍真实项目里最常见的套路。文章我会按照自己实际开发时的推进顺序来写——先讲业务建模和数据表设计再讲SpringBoot接口层然后是MyBatis统计SQL和Vue前端联调最后是部署和排坑经验。学到的不只是几个框架怎么用而是这些框架在一个具体业务场景里是怎么配合起来的。1. 智能家居销量分析的痛点与jrabo系统的业务建模1.1 数据分散、口径不一为什么一定要做这个系统在聊技术实现之前得先说说业务背景因为表结构、接口、页面全部是由业务驱动的。智能家居类目的销量数据和普通快消品有很大区别产品SKU多、单价差异大、渠道性质完全不同。比如一个智能门锁卖一千多一个智能插座只卖几十块单纯统计“订单数量”没有意义必须同时统计销售额还要按不同价格带拆开看才有价值。当时项目启动的直接原因是运营每周都在重复做同一件事从各平台后台导出Excel再手工把“产品型号、渠道名称、销量、销售额”填进一张总表。订单一多数据就开始对不上——今天京东口径包含定金订单明天淘宝口径不包含退款单加减几次之后谁也不敢说哪个数字准。这种状态下别说分析“哪些产品带动了增长”连基本的“上月总销售额”都要扯皮半个月。jrabo系统的目标就非常明确把分散的订单流水统一收进MySQL由后端接口按统一的统计口径计算销量和销售额前端再把这些指标用表格和图表展示出来。口径一旦在SQL层固定了所有人都只认这一个结果扯皮自然就停了。换句话说这套系统表面上是个数据展示平台本质上做的是业务口径的统一和透明化。1.2 核心功能清单从订单录入到多维统计报表做完业务抽象之后功能模块其实可以收敛得很干净。基础数据维护、订单数据管理、统计分析和可视化为四个主要模块。基础数据维护里最核心的是产品档案产品分类、型号、单价、发售日期这些信息都放在产品表里。订单数据管理则负责订单流水的导入和手工录入这是我们当时比较在意的一个点——因为各个渠道的数据格式五花八门所以为订单导入预留了按照Excel模板批量导入的扩展位基础的增删改查先跑通。统计分析是重头戏。jrabo系统支持按时间范围日、周、月统计销量和销售额支持按产品维度、产品分类维度、渠道维度三种方式聚合并且带一个简单的销量排行功能——超过预警阈值的商品会标红展示。这些能力全部由后端接口提供前端页面只负责传筛选条件和渲染结果。可视化层面做得比较实在没有堆太多花哨的功能就是三个核心视图销售趋势折线图、分类销量占比饼图、产品销量排行柱状图。这三个视图对应着运营日常看得最多的三个问题整体走势如何、哪个品类贡献最大、卖得最好的是哪款单品。页面顶部放一个筛选条件区域所有图表和表格共用同一组筛选条件这样整个页面的分析逻辑是连通的。1.3 数据表设计订单流水和产品档案的建模要点数据库我用的是MySQL 8.0字符集统一设置为utf8mb4这个选择后面会细说原因。整个系统只需要两张核心业务表加几张辅助表结构非常清晰。产品表product字段包括主键id、产品名称、分类category、型号model、单价price、渠道channel——不过仔细想了一下渠道不应该挂在产品表上因为同一个产品会在多个渠道销售所以我最终把渠道字段从产品表拿掉做成订单表里的一个维度字段。这个建模过程是在实际开发中调整过的一开始为了图省事把产品和渠道绑在一起后来发现统计“线上和线下各自卖了多少”时会非常别扭于是果断拆开。这也是做数据分析类项目时的一个通用经验凡是经常作为“分组依据”的字段不要挂在主档表上放在明细表里会灵活得多因为明细表天然适合GROUP BY。订单表orders字段包括主键id、订单编号order_no、产品id product_id、下单时间order_date、渠道channel线上/线下、销量quantity、销售金额amount。这里我额外加了region区域字段用来支持按地区维度统计虽然页面暂时没展示但接口已经预留了。订单表的索引设计是这次项目中我自己比较满意的部分order_date建立普通索引、product_id建立普通索引、channel单独建索引并且做了一个联合索引(order_date, product_id, channel)。为什么做联合索引因为统计分析中最常见的查询条件就是“某段时间内、某个产品、某个渠道的销量”联合索引能同时过滤掉三个维度性能会好很多。对于订单量在几十万级别的系统这个索引优化基本能达到毫秒级响应。2. SpringBoot后端接口分层、参数校验与Maven构建2.1 工程结构设计与依赖选择后端采用标准的SpringBoot MyBatis MySQL结构我用的是SpringBoot 2.7.x版本Java 8。为什么不选3.x当时考虑到很多生产环境的JDK版本还是8而且SpringBoot 3.x要求Jakarta命名空间改造、javax要全部换成jakarta如果有老代码迁移经验的朋友会懂这有多麻烦。如果是全新项目选3.x没毛病但2.7.x的生态兼容性更好尤其是MyBatis相关的各种插件都不用额外适配。工程结构用经典的Maven三层结构jrabo-system/ ├── pom.xml ├── src/main/java/com/jrabo/ │ ├── controller/ # REST接口层 │ ├── service/ # 业务逻辑层 │ ├── mapper/ # MyBatis的Mapper接口 │ ├── entity/ # 实体类Product、Orders等 │ ├── dto/ # 接口入参和返回对象 │ ├── config/ # 跨域、MyBatis等配置类 │ └── JraboApplication.java ├── src/main/resources/ │ ├── mapper/ # MyBatis的XML文件 │ └── application.yml └── src/main/scripts/ # 数据库初始化脚本对于这种规模的项目三层架构就够了没必要引入DDD那套复杂的分层方式。pom.xml里关键的依赖就五个spring-boot-starter-web、mybatis-spring-boot-starter、mysql-connector-java、lombok、fastjson。如果要做单元测试再加一个spring-boot-starter-test。这里要注意MySQL驱动版本与MySQL服务版本的匹配我当时用的是mysql-connector-java 8.0.28如果MySQL是5.7用5.1.x驱动反而更顺。https://mvnrepository.com/可以查看每个依赖的可用版本列表比IDE里自动提示的信息全不少。2.2 REST接口设计与日期参数的处理细节接口层我严格按照REST风格设计总共四个核心接口全部以/api开头。产品管理接口负责产品档案的增删改查订单管理接口负责订单的录入、删除和分页查询统计查询接口是本系统的核心——接收筛选条件和聚合维度返回统计结果列表销量排行接口则按指定时间范围和渠道对产品销量进行排序。写统计接口的时候有个细节值得单独拿出来讲前端传日期参数后端的接收方式。一开始我用的是两个String类型参数startDate和endDate然后在Service里用SimpleDateFormat解析成Date类型但这样有两个隐患。一是DateFormat不是线程安全的在并发请求下可能出现日期错乱或者解析异常二是前端传啥格式后端就得严格配合一旦格式不统一比如前端传了带时分秒的格式解析就报错。后来我改成用LocalDate和LocalDateTime配合Jackson的日期格式化注解来处理代码更简洁线程安全性也天然保证。接口参数接收形如2025-01-01这样的日期字符串配合注册一个Jackson自定义配置来统一解析。在这一步能明显感受到Java 8时代和旧版Java的差异LocalDate的用法熟悉之后日期处理基本不会出错。统计接口的入参我定义成了一个StatsQueryDTO包含startDate、endDate、productId、category、channel、groupBy六个字段其中groupBy的取值是day、product、category、channel。接口的返回对象同样用一个统一的Result封装code为200表示成功数据放在data里。为什么统一返回结构因为前端Axios拦截器需要根据code做统一处理如果每个接口返回格式都不一样拦截器就得为每个接口写分支判断维护成本高这是前后端接口设计中一个非常基础但重要的约定。2.3 Service层的统计逻辑与查询流程Service层是这个系统的业务核心。以“按时间统计销售额”这个最常用的查询为例它的处理流程是先校验参数合法性和时间范围跨度是否超过限制防止一次性查跨五年的数据直接把数据库拖垮然后根据groupBy的值调用不同的Mapper查询方法最后对查询结果做简单的后置处理比如为空时用0补位——这样前端画折线图时不会出现断点这个处理对展示体验的提升非常明显是运营那边主动提的需求因为图表上的数据如果缺几天看上去就不连续容易让人误以为数据丢了。订单录入走的是另一个逻辑分支录入时会先确认产品id有效且处于上架状态然后校验渠道字段是否在枚举范围内最后计算订单总额并写入数据库。这些校验逻辑全部放在Service层不放在Controller里——Controller只负责参数绑定、调用Service、返回结果任何业务规则都不该出现在Controller层。我一直认为这个分层原则是让代码后期可维护的基础如果不遵守Controller迟早会变成各种逻辑堆叠的大杂烩这是很多Spring项目后期改不动的主要原因。事务边界也是我在这个项目中认真思考过的点只有订单批量导入这个方法加了Transactional因为它是多张表写入操作任何一个订单失败都应该回滚整个批次。单纯的统计查询方法不加事务因为查询操作根本不涉及写数据加上事务反而会增加无谓的连接占用。很多初学者容易犯的错误是做加法——所有方法都加Transactional看起来保险实际上在高并发查询场景下会拖垮连接池。2.4 实测中的Maven构建与版本适配Maven构建这块我踩的坑主要集中在这几个地方一是SpringBoot版本选太高。我最初试过用SpringBoot 3.0跑这个项目结果MyBatis starter不兼容、javax.servlet全要换最后老老实实退回2.7.5问题立刻消失。如果你的项目也用到了比较老牌的第三方库建议先确认它们对SpringBoot 3.x的适配情况不要盲目跟着最新版本走。二是Lombok版本和JDK版本不匹配。如果JDK版本是11以上老版本Lombok生成的代码会有编译问题最简单的解决办法是直接用spring-boot-starter-parent的dependencyManagement来统一管理Lombok版本这样它会自动适配当前SpringBoot对应好用的Lombok版本。三是项目打包时如果引用了本地jar文件需要在pom.xml里配置systemPath但更推荐部署到私有仓库否则团队协作时其他人本地会直接编译失败。命令方面构建打包用Mavenmvn clean package -DskipTests跳过测试可以节省不少时间尤其是本地运行时不需要每次跑一遍单元测试。打包完成后target目录下会生成jrabo-system.jar这就是可以交付部署的产物了。3. MyBatis统计SQL与XML动态配置的实战拆解3.1 销量数据聚合的核心SQL语句MyBatis是这套系统里直接和MySQL打交道的层如果业务不复杂用注解开发完全可行但涉及动态条件查询时XML是更合适的选择。因为XML可以动态拼接SQL片段可读性和维护性比注解里的字符串拼接好太多。拿最核心的销量趋势查询SQL来说需求是按天统计销量和销售额。对应的Mapper XML长这样select idselectSalesTrend resultTypecom.jrabo.dto.SalesTrendDTO SELECT DATE(o.order_date) AS statDate, SUM(o.quantity) AS totalQuantity, SUM(o.amount) AS totalAmount FROM orders o where if teststartDate ! null AND o.order_date gt; #{startDate} /if if testendDate ! null AND o.order_date lt; #{endDate} /if if testchannel ! null and channel ! AND o.channel #{channel} /if /where GROUP BY DATE(o.order_date) ORDER BY statDate /select这条SQL就是整个系统统计功能的地基。DATE函数把完整的order_date字段截断成日期部分然后按天分组再用SUM聚合销量和金额。这里有几个细节值得注意order_date字段的类型我设计的是DATETIME因为订单在一天内可能有多次记录如果直接按天分组必须用DATE函数转换。索引前面提到过所以当数据量增大时这条SQL依然能保持较好的响应速度。3.2 动态SQL组合筛选条件的核心用法动态SQL是整个统计系统灵活性最大的地方也是MyBatis最实用的特性之一。jrabo系统的统计查询支持六种筛选条件的自由组合——时间范围、产品id、分类、渠道、区域、排序规则。如果每个组合都写一条SQL那可能得写二三十条而用动态SQL一条查询就能覆盖所有场景。动态SQL的关键标签是where和if。我用if标签判断每个条件是否为空为空就不拼进SQL。用where标签自动处理AND前缀避免SQL语法错误。在按产品分组统计的接口里还用了choose和when标签来处理sortField字段实现按销量或销售额动态排序效果和多个if是一样的。format一波我在MyBatis工作流里常用的逻辑用户在页面把筛选条件设好前端把参数封装成JSON传给后端后端接收到参数后传递给MyBatisMyBatis在解析XML时根据参数值动态拼装SQL最终执行得到结果。了解这套机制后你就能把握住一个原则MyBatis的XML文件里写的是“模板”而不是固定SQL运行时才决定最终形态。这也是为什么MyBatis能成为Java生态里使用最广的ORM框架之一。3.3 驼峰命名映射和连表查询的字段丢失问题这个坑我印象特别深因为当时花了大半天排查。MyBatis在将数据库列名映射到Java实体属性时默认情况下是按列名和属性名完全一致来匹配的。MySQL中习惯用下划线风格命名列比如order_date、total_amount而Java实体类习惯用驼峰风格比如orderDate、totalAmount。如果不做任何配置查询结果中orderDate会是null——数据查出来了但又好像没查出来。解决办法是在application.yml中开启驼峰映射开关mybatis: configuration: map-underscore-to-camel-case: true开启之后MyBatis会自动把下划线风格的列名转换为驼峰风格的属性名。这个配置虽然只需要一行但漏配的代价很高。另外还有一个更容易被忽略的点在编写连表查询时如果是多表关联且两张表有同名字段比如orders表和product表都有一个category字段需要给字段取别名。否则MyBatis拿到ResultSet后找category字段的值但同名字段不知道取哪个极易得出错误结果。我在jrabo系统的订单分页查询里就遇到过这个问题orders表里有个remark字段product表里也有remark字段不加别名时返回的remark全变成了product表的。这种问题不像空指针那么好察觉因为它不报错只是数据不对定位起来很费劲。3.4 MySQL时区与排序的注意事项MySQL统计查询里还有两个容易被忽略的问题一个是时区一个是中文字段排序。时区问题表现为数据库存的是UTC时间而Java程序读取时连接驱动默认使用服务端的时区设置如果服务端时区设置不合理可能产生8小时的时间偏移。我当时用Navicat查了半天数据都没问题Java接口一查就发现统计日期整体晚了一天最后发现是MySQL连接串少了时区参数。正确的写法是在JDBC连接串里明确指定jdbc:mysql://localhost:3306/jrabo?serverTimezoneAsia/ShanghaiuseSSLfalsecharacterEncodingutf8mb4serverTimezone参数能避免时区错乱useSSLfalse可以避免MySQL 8.x强制SSL连接导致一些旧驱动报错这在热词里看到的“mysql ssl连接错误”问题也大多由这里引发。中文字段排序则是另一种情况如果希望产品分类按照拼音排序需要给分类字段设置utf8mb4_general_ci或更贴近业务的排序规则。其实后来我发现统计系统对分类的排序需求通常不是字典序而是按销量排序所以这个优先级并不高了解排序规则的大致原理即可。4. Vue前端从页面到图表的完整联调链路4.1 Vue工程选型与基础配置前端我用Vue 2 Element UI ECharts的组合这也是国内中小型项目里非常普遍的一套。技术上Vue 3 Vite肯定是更现代的选择但考虑到项目里需要快速上手维护Vue 2的生态资料更丰富Element UI的组件成熟度也足够所以就沿用了。如果你是重新选型Vue 3 Vite Element Plus会更主流选型前后并不影响本文的核心思路。工程创建建议直接使用脚手架Vue 2对应vue-cliVue 3对应create-vue或者vite。当前端项目生成之后我会先做三件事清理默认的HelloWorld组件、配置路由、配置环境变量。环境变量里最有价值的是统一设置后端接口地址我在.env.development里写VUE_APP_BASE_URL这样后端接口地址调整时只需要改配置而不用到每个页面文件里找。Vue工程的基础目录结构按功能划分api目录统一放接口请求函数views目录放页面组件components目录放可复用组件utils目录放公共工具函数。这次我把封装的Axios请求实例放在utils/request.js里面单独维护一个Axios实例这种做法在团队协作时尤其有用——新增接口时只需在api目录里加一个函数不用关心请求细节。4.2 Axios封装与跨域代理的配置细节Axios封装是这次前端项目里对实际开发效率提升最大的一件事。我封装成一个可以直接导入的request实例配置了统一的baseURL、请求超时时间、请求拦截器和响应拦截器。请求拦截器负责在请求头中附带认证token——虽然jrabo系统的鉴权在初版做得比较浅但结构上先预留了响应拦截器则统一处理返回数据当code为200时直接返回data给业务层非200时弹出错误提示并把后端返回的message展示出来。这样做能大幅减少业务代码里对错误分支的重复处理。前后端分离最大的挑战其实是跨域。前端开发环境跑在8081端口后端跑在8080端口浏览器里直接从8081访问8080就是一种跨域行为。从头解决跨域传统做法是在后端写CORS配置但从开发体验角度来看更稳妥的其实是让Vue的开发服务器把请求代理到后端——前端请求仍然从8081发出Vue CLI的devServer拦截到指定前缀的请求后转发到真实的后端地址这样浏览器看到的请求是同源的跨域问题就消解了。配置如下// vue.config.js module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } }这里有一个细节需要区分locate上是否使用pathRewrite重写。我前后端约定的接口前缀是/api后端Controller的RequestMapping也带/api前缀那么proxy里不需要做pathRewrite直接原样转发即可。只有当前端以/api标识代理但后端接口没有这个前缀时才需要重写路径去掉/api。建议在项目一开始就定好统一规则前端所有请求统一走/api前缀。如果不做统一约定部署后你会发现部分接口走代理服务、部分接口直连后端非常乱。4.3 筛选区、表格与图表的联动实现前端最核心的页面是销售统计页它由四部分组成筛选条件区、统计表格、三个主图表、一个最近订单列表。筛选区组件包含时间选择器、产品下拉框、渠道单选按钮、分类下拉框和查询按钮。用户点击查询按钮后组件会把所有筛选条件组装成对象调用API函数向后端发送统计请求拿到结果后分别传给图表组件和表格。图表组件采用ECharts我用到了折线图、饼图和柱状图。折线图展示销售趋势x轴是日期y轴是销售额饼图展示分类销量占比柱状图展示产品销量排行。三者共享同一份统计数据只是分别做了不同的数据映射。写代码时的核心是把后端返回的列表转换成ECharts所需的series格式。这个过程看似简单但涉及map/reduce的处理如果封装不好图表组件里会充斥各种转换逻辑。我的做法是在api层就完成数据格式化拿到后端数据后直接传递给组件——图表组件里只负责渲染不参与数据处理。这样做的好处是后端接口如果调整了返回字段只需要改api层的转换函数不用动十几个图表组件。联调过程中最常遇到的问题就是字段对不上后端返回statDate和totalAmount前端误写成statdate和totalamount结果图表一片空白。这类问题通过浏览器的开发者工具Network面板就能快速定位查看接口返回数据的实际字段名然后和前端代码对比基本不需要后端介入。我把这种排查能力当成前后端联调的基本功掌握了它合作起来的摩擦会少很多。4.4 发布环境的静态资源与路由模式前端开发完成后需要执行构建命令生成静态资源。Vue2项目是npm run build:prodVue3 Vite项目是npm run build构建产物都输出到dist目录。dist目录里的东西最常见的做发方式是交给nginx托管或者拷贝到SpringBoot的static目录由后端托管。我在后面的部署章节会详细讲两种方式。前端这边需要额外注意的是路由模式如果使用history模式在nginx里需要配置try_files机制否则刷新页面时会遇到404错误。在开发环境这个问题不会出现因为devServer已经处理了路由回退但部署到nginx时很容易被忽略。使用hash模式虽然不用配这个但URL里会多一个#号看起来不专业。权衡之下我选择history模式并在nginx配置里加一行try_files。5. 完整部署实战环境准备、打包、运行与排障5.1 环境版本匹配与准备部署之前先把环境明确下来。我当时用的是CentOS 7服务器加宝塔面板辅助管理如果你用Windows服务器或者腾讯云轻量服务器过程类似。版本匹配清单如下组件推荐版本备注JDK1.8兼容SpringBoot 2.7.xMaven3.6.3构建后端项目MySQL5.7或8.0字符集选utf8mb4Node.js14或16构建前端项目Nginx1.20托管前端静态资源务必注意JDK和SpringBoot版本的对应关系。SpringBoot 2.7用JDK8没问题SpringBoot 3必须JDK17以上。如果你按我的方案走JDK8就够了。MySQL如果用8.0记得在前面提到的JDBC连接串里加上serverTimezone参数。Node版本方面Vue CLI项目在Node16下构建比较顺畅Node18在某些情况下会报OpenSSL相关的错误——这就对应了热词里“vue安装及环境配置”相关搜索中最常见的问题出现这类问题通常可以用NODE_OPTIONS--openssl-legacy-provider npm run build临时解决但治本方法是换Node16。5.2 数据库初始化与后端服务启动拿到完整源码后第一步是初始化数据库。源码里通常带一个document/sql目录里面放着jrabo_init.sql脚本。执行步骤为先用root账号连接MySQL创建数据库并设置字符集再导入SQL文件。需要注意导入SQL时如果脚本里有CREATE DATABASE语句就不用在命令行里先建库直接从命令行导入即可。执行完脚本后可以用SHOW TABLES检查一下应能看到product、orders等数据表。接着配置后端application.yml里的数据库连接。文件路径是src/main/resources/application.yml需要修改MySQL地址、账号、密码这三项。如果和数据库在同一台服务器上地址填localhost即可。改完之后在项目根目录执行构建命令构建成功后target目录下会出现jar文件。启动命令是java -jar jrabo-system.jar启动完成后看日志出现“Started JraboApplication”即可确认成功。jrabo后端默认端口是8080保证服务器安全组里放行这个端口否则外网无法访问。5.3 前端构建与部署的两种方式前端部署有两条路我实际都跑过各有利弊。方式一是用Nginx托管这是最标准也最推荐的方式。构建前端项目把dist目录里的所有文件上传到服务器的/www/jrabo-dist目录然后编辑Nginx配置设置root指向这个目录location /api块用作反向代理后端8080。这种方式前后端彻底分离后端升级不会影响前端页面上线时只需替换静态文件所以生产环境我都推荐这种方式。方式二是把前端dist文件拷贝到SpringBoot的resources/static目录和Java代码一起打进jar包启动SpringBoot后直接访问8080端口即可看到页面。这种方式适合个人项目或演示场景省去了安装Nginx的步骤但前后端分离的意义就没有完全发挥出来因为静态资源和API挤在一个进程里。两种部署方式背后是同一个前置工作如果前端代码里的接口地址是从.env文件读取的相对路径/api那么开发时用代理、部署时由Nginx转发前端就基本不用改代码。如果用绝对URL写死后端地址开发环境和生产环境就必须频繁修改代码那会很麻烦。我的经验是工程初始化时就把环境变量机制配好一次性解决两个环境的切换问题。5.4 常见启动失败与排查手册最后把自己在这次部署中遇到过的典型问题梳理成一份排查手册方便你对照。端口被占用最常见。启动SpringBoot报8080端口被占用用netstat -ntlp命令查一下占用端口的进程换个端口或者kill掉占用进程即可。数据库连接失败最常见的原因是MySQL账号权限不足或密码含特殊字符。MySQL密码如果包含、#等字符在application.yml中需要特殊处理必要时用引号包裹或改简单密码。MySQL 5.7和8.0的密码加密规则不同如果连接报Authentication plugin错误可以更新用户认证方式。前端页面能打开但接口报404或502优先检查Nginx代理配置。尤其要注意location /api块的proxy_pass地址后面有没有斜杠结尾这个细节很多教程容易写漏会导致转发路径错误。window.page的报错大多与后端接口返回的数据结构和前端期望的不匹配有关在Network面板里查看接口实际返回多半能快速定位。静态资源404的问题则是Nginx部署最常见的坑。打包上传后刷新页面发现CSS、JS加载不出来多半是root路径配置不对。Nginx里的root指向的是dist目录而不是dist下某个子目录路径不对会导致所有静态资源的引用地址全部偏移。通过浏览器开发者工具看到404资源的请求路径对照Nginx配置就能判断问题。注意部署完成后一定要用curl -I http://localhost:8080/api/product/list这类命令先在后端本机测试接口是否通再从前端页面测试。如果接口在服务器本机都调不通就不用浪费时间去查前端了。写在最后这套jrabo系统从立项到跑通大概用了三周业余时间真正写代码的时间其实没占多少大量的时间花在版本匹配、字段对齐、联调排查这些琐碎但无法跳过的环节上。你在跑通这个项目时如果遇到问题优先看一下是不是配置层面的疏漏而不是怀疑代码本身有问题——大概率是环境差异导致的。如果时间允许建议你在跑通基础功能后试着把它往自己熟悉的业务方向扩展下比如把订单导入做成Excel批量解析把统计分析导出成PDF报告或者给产品加一个库存预警字段。骨架在的时候加业务功能只是往里填砖的事。希望这篇记录能让你少踩一些我已经踩平的坑。
返回列表