ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

C# .NET与Vue仓库管理系统实战:前后端分离架构与部署

C# .NET与Vue仓库管理系统实战:前后端分离架构与部署 简介这是一套基于C# .NET Web API与Vue.js实现的前后端分离式仓库管理系统源码面向需要快速落地企业级库存管理模块的开发者、毕业设计学生及求职项目储备者解决传统单体架构复用性差、前后端耦合度高、权限与跨域处理不规范等实际开发痛点。资源共243个文件涵盖112个C#后端逻辑文件含JWT鉴权过滤器、Swagger接口文档配置、19个Vue组件页面、20个CSS样式与17个JS交互脚本以及Web.config跨域配置、Global.asax启动项、.sln解决方案等核心工程文件压缩包仅9.48MB轻量易部署。已有767人学习下载代码结构清晰完整呈现Bearer Token登录流程含Token生成、响应封装、控制器级Options预检处理、Swagger自动生成API文档、Web API跨域集成等关键实践细节可直接用于二次开发或作为.NETVue全栈学习范例。 做仓库管理系统这几年前后端分离已经成为标配但很多朋友在真正动手时还是会被一些细节卡住。比如接口怎么设计才算合理、权限怎么控制才够安全、Vue端和.NET后端到底怎么联调最顺畅。这套基于C# .NET Vue的仓库管理系统我把PC端和server端完整走了一遍从数据库设计到接口开发再到前端页面踩了不少坑也沉淀了一套可以直接抄作业的方案。无论你是刚接触前后端分离的新手还是想找一套完整参考的开发者这篇内容都能给你实在的帮助。1. 项目背景与整体架构设计1.1 为什么选择C# .NET Vue这套组合先聊点实在的。仓库管理系统这种业务型项目选型最怕两头不到岸。纯前端方案撑不起复杂业务逻辑纯后端又没法做出好的交互体验。C# .NET做服务端稳定性高、并发处理能力强尤其在企业内部系统里有天然优势——大部分公司IT环境都是Windows部署维护成本低。Vue作为前端框架上手曲线平缓、生态成熟配合Element UI这类组件库做后台管理系统的效率非常高。前后端分离架构下后端只需要提供标准化的RESTful API前端完全通过HTTP请求进行数据交互互不干扰。这套系统里我用了.NET 8 Vue 3整体表现非常稳。接口响应时间普遍在50ms以内即便在万级数据量的库存表上做分页查询也没有明显卡顿。适合参考这套方案的读者我建议是这几类已经在做.NET后端想补前端能力的、做Vue前端想理解后端接口设计的、以及需要一套完整前后端分离实战案例来做毕设或公司项目的。技术栈其实不算新但前后端分离的完整链路——从环境搭建到联调部署——是很多教学资源覆盖不到的。1.2 仓库管理系统的核心业务模块拆解仓库管理系统听起来简单真正拆解起来业务模块不少。我把它分成六大核心模块用户权限、基础档案、入库管理、出库管理、库存管理和报表统计。每个模块不是独立存在的它们之间通过单据和库存表互相联动。用户权限模块负责登录认证、角色分配、菜单权限控制基础档案管理物料信息、供应商、客户、仓库和货位入库管理处理采购入库、退货入库、生产入库出库管理对应销售出库、领料出库、退货出库库存管理则是核心中的核心实时更新库存快照、锁定库存、库存预警报表统计对进出库数据进行汇总分析给管理层做决策参考。模块划分的核心思路是单据驱动、库存联动。所有库存变化必须通过单据触发不允许直接修改库存表。这一点非常关键因为仓库系统最怕数据不透明库存一旦可以随便改后面整个报表都是废的。我在设计数据库时就定了规矩库存流水只增不改库存当前值只是流水的最新快照。1.3 前后端分离的数据流设计思路前后端分离后最大的变化是数据流从页面刷新获取变成了接口异步请求。前端Vue通过axios发起HTTP请求后端Web API接收请求并处理业务逻辑从数据库读取数据后返回JSON前端再渲染到页面上。这套系统的数据流向我梳理成一条主线前端页面 → 路由守卫校验登录态 → Axios请求拦截器附带Token → 后端JWT认证中间件验证身份 → 控制器接收参数 → 业务逻辑层处理 → EF Core访问数据库 → 返回统一JSON格式 → 前端响应拦截器解析数据 → 页面组件更新视图。为了规范这套流程我在后端定义了一个统一响应格式成功时返回{ code: 200, data: ..., message: 操作成功 }失败时返回对应错误码和提示信息。这样前端拦截器只要判断code是否为200统一处理成功和异常不用每个页面单独写错误判断。2. 后端C# .NET Web API核心实现2.1 项目结构与分层设计后端我用的是经典三层架构基础上演进的方案按职责拆成四个项目Api层控制器和启动配置、Service层业务逻辑、Repository层数据访问、Models层实体类和DTO。这样做的好处是各层职责清晰后期维护不用到处找代码。实际结构是这样的Solution/ ├── Warehouse.Api/ # Web API层 │ ├── Controllers/ # 控制器 │ ├── Middleware/ # 中间件异常处理、JWT │ └── Program.cs ├── Warehouse.Service/ # 业务逻辑层 │ ├── IInventoryService.cs │ └── InventoryService.cs ├── Warehouse.Repository/ # 数据访问层 │ ├── InventoryRepository.cs │ └── DbContext.cs ├── Warehouse.Models/ # 实体模型与DTO │ ├── Entities/ │ └── DTO/分层设计的核心价值是可替换性。比如你前期用EF Core后期觉得性能不够想换Dapper只需要改Repository层的实现Service层完全不用动。我实际做项目时经常遇到这种需求变更分层带来的便利是实实在在的。2.2 数据库设计与EF Core映射数据库是仓库管理系统的根基。我的表设计遵循三个原则主键统一用雪花ID不用自增ID方便分库分表和数据迁移、所有业务表都带创建时间和操作人字段、关键表设计唯一约束防止重复数据。核心表结构我整理了一张工作量最大的就是这几张表名核心字段说明UsersId, UserName, PasswordHash, RoleId用户表密码存哈希不存明文RolesId, RoleName, Permissions角色表权限用JSON格式存储MaterialsId, MaterialCode, MaterialName, Spec, UnitId物料档案表WarehousesId, WarehouseName, Location仓库表StockId, MaterialId, WarehouseId, Quantity, LockedQuantity库存快照表StockFlowId, MaterialId, WarehouseId, ChangeType, ChangeQuantity, BeforeQuantity, AfterQuantity库存流水表InboundOrderId, OrderNo, SupplierId, Status, TotalAmount入库单主表InboundItemId, OrderId, MaterialId, Quantity, Price入库单明细表EF Core映射我用的是Fluent API写实体配置没用Data Annotation因为Fluent API可以把所有配置集中管理表结构变更时不用满世界找特性标记。下面这段是库存表的配置示例public class StockConfiguration : IEntityTypeConfigurationStock { public void Configure(EntityTypeBuilderStock builder) { builder.ToTable(Stock); builder.HasKey(x x.Id); builder.Property(x x.Quantity).HasPrecision(18, 2); builder.HasIndex(x new { x.MaterialId, x.WarehouseId }).IsUnique(); } }注意那个联合唯一索引这是防止相同物料在相同仓库出现两条库存记录的兜底措施。我在实际运维中确实遇到过因为并发导致重复数据的情况这个约束能保证即使代码出bug也不会污染数据。2.3 JWT认证与权限控制详解仓库管理系统几乎没有不需要登录就能访问的页面认证和权限是安全底线。我选用JWTJSON Web Token而不是传统的Session方案原因在于前后端分离场景下JWT天然无状态服务器不需要保存会话信息非常适合分布式部署。JWT生成逻辑在登录接口中验证用户名密码后生成Token包含用户ID、用户名、角色ID和过期时间用密钥签名后返回给前端。前端在后续请求的Header中携带Authorization: Bearer {token}后端中间件自动解析验证。var claims new[] { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.Role, user.RoleId.ToString()) }; var key new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config[Jwt:Key])); var credentials new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token new JwtSecurityToken( issuer: _config[Jwt:Issuer], audience: _config[Jwt:Audience], claims: claims, expires: DateTime.Now.AddHours(8), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token);过期时间我设置了8小时工厂上班时间正好覆盖。这里有个容易被忽略的点密钥长度必须满足HmacSha256的最低要求至少16个字符否则运行时会直接抛异常。不少新手在这踩坑。权限控制上用访问令牌的方式实现。在需要权限的接口上标注[Authorize]在需要特定角色的接口上标注[Authorize(Roles Admin)]。但我的实际经验是不要过度依赖角色硬编码因为业务里经常出现角色一样但能看的菜单不同的需求所以我把前端菜单权限和后端接口权限分开控制后端管接口访问权前端管菜单显示权两者通过角色下的权限列表关联。2.4 核心业务接口实现入库、出库、库存入库接口是整个系统的典型业务涉及主表、明细表、库存表、流水表四张表的操作必须放在一个数据库事务里。我用的是EF Core的IDbContextTransaction任何一步失败就整体回滚。public async TaskResultDto CreateInboundOrder(InboundOrderCreateDto dto) { using var transaction await _context.Database.BeginTransactionAsync(); try { var order new InboundOrder { OrderNo GenerateOrderNo(RK), SupplierId dto.SupplierId, Status 待审核, CreatedAt DateTime.Now }; await _context.InboundOrders.AddAsync(order); await _context.SaveChangesAsync(); foreach (var item in dto.Items) { // 写入明细 var orderItem new InboundItem { OrderId order.Id, ... }; await _context.InboundItems.AddAsync(orderItem); // 更新库存存在则累加不存在则新增 var stock await _context.Stocks .FirstOrDefaultAsync(s s.MaterialId item.MaterialId s.WarehouseId dto.WarehouseId); if (stock ! null) { stock.Quantity item.Quantity; } else { await _context.Stocks.AddAsync(new Stock { ... }); } // 写流水 await _context.StockFlows.AddAsync(new StockFlow { MaterialId item.MaterialId, ChangeType 入库, ChangeQuantity item.Quantity, BeforeQuantity stock?.Quantity ?? 0, AfterQuantity (stock?.Quantity ?? 0) item.Quantity }); } await _context.SaveChangesAsync(); await transaction.CommitAsync(); return ResultDto.Success(order.Id); } catch { await transaction.RollbackAsync(); throw; } }注意流水表里我记录了BeforeQuantity和AfterQuantity这不仅是可追溯的需要后期做数据对账时能直接对比每笔单据对库存的影响排查问题效率翻倍。出库接口逻辑类似但有个额外动作检查库存是否充足而且要用锁定库存的概念来防止超卖。我的做法是先在库存表里扣减LockedQuantity锁定数量实际出库确认时再扣减Quantity并释放锁定。这样可以防止订单提交后、出库确认前别的订单把货抢走了。3. 前端Vue 3 Element Plus实现3.1 前端工程化架构前端我选的是Vue 3 Vite Element Plus Pinia Vue Router的组合。Vite取代Webpack后开发环境的冷启动速度提升非常明显不再有漫长等待的痛苦。用npm create vitelatest创建项目后再安装对应依赖模块。目录结构我延续了实际项目规范化的做法src/ ├── api/ # 接口统一管理 │ ├── auth.ts │ ├── inventory.ts │ └── stock.ts ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── layout/ # 布局组件 ├── router/ # 路由配置 ├── stores/ # Pinia状态管理 ├── utils/ # 工具函数axios封装、格式化等 └── views/ # 页面视图每个模块的接口调用统一放在api目录下页面组件不直接写axios地址。这样后端接口地址变动时只需要改一个文件不用全局搜索替换。路径别名用指向src目录避免写一长串相对路径。3.2 登录状态管理与动态路由前端登录流程是整套系统的入口环节处理不好后续全乱。用户在登录页输入账号密码调用后端登录接口获取Token和用户信息然后把Token存储到localStorage用户信息存到Pinia中。路由守卫每次跳转前检查是否存在Token没有Token就直接重定向到登录页。router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.path ! /login !token) { next(/login); } else if (to.path /login token) { next(/); } else { next(); } });动态路由是权限控制的关键实现。用户登录后后端返回该用户拥有权限的菜单和按钮编码列表前端遍历这个列表动态生成路由表用router.addRoute注册到路由器中。这样用户没权限的模块连路由都不存在直接在入口拦截掉。一个重要的细节动态路由需要持久化。页面刷新后Vue实例重建需要重新从后端拉取路由配置。所以我把用户权限信息在Pinia中做了缓存刷新时先检查缓存没有就从后端拉取再走动态路由注册流程。3.3 Axios封装与请求拦截器Axios封装是前端项目的核心基建。我封装的主要目的有三个统一附加Token、统一处理错误码、统一格式化响应数据。这里展示封装的核心逻辑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) { return res; } if (res.code 401) { localStorage.removeItem(token); router.push(/login); return Promise.reject(new Error(登录已过期)); } ElMessage.error(res.message || 请求失败); return Promise.reject(new Error(res.message)); }, error { ElMessage.error(网络异常请稍后重试); return Promise.reject(error); } );超时时间设置10秒仓库系统在弱网环境下的操作频率不高这个时间足够。响应拦截器中碰到401就直接清Token跳登录页这是很多项目都会忽略但极其重要的设计。如果没有这一步用户Token过期后每个接口都会报错页面一堆红条提示体验很差。3.4 仓库作业页面的关键交互实现仓库作业页面最核心的交互是单据录入。以入库单为例用户需要先选择供应商和仓库然后再明细区域动态增加物料行填写数量、单价还有弹窗搜索物料的功能。物料选择弹窗是这类页面的重灾区数据量大了以后一次性拉全部物料会导致首屏卡死。我采用的是远程搜索方案输入关键字后调用后端接口模糊查询接口限制条数最多返回20条。这样既保证了用户体验又不给服务器造成压力。el-select v-modelmaterialId filterable remote :remote-methodsearchMaterial placeholder请输入物料编码或名称 el-option v-foritem in materialOptions :keyitem.id :labelitem.materialCode - item.materialName :valueitem.id / /el-select库存盘点页面用到了高亮和编辑状态切换用户在表格中直接输入实盘数量系统自动对比账面数量和实盘数量差异部分高亮显示。这一步前端用computed属性做实时计算就够不用每个格子都请求后端保存时再一次性提交差异数据性能体验都好很多。4. 前后端联调与生产环境部署4.1 本地开发跨域与代理配置前后端分离开发阶段最大的拦路虎就是跨域。前端开发服务器跑在5173端口后端API跑在5000端口浏览器直接请求会触发CORS策略。我用的方案是前端代理不是后端开启CORS。虽然开发时后端开启CORS也能解决但生产环境部署后反而容易埋下安全隐患。Vite配置代理非常方便修改vite.config.tsexport default defineConfig({ server: { proxy: { /api: { target: http://localhost:5000, changeOrigin: true, rewrite: path path.replace(/^\/api/, ) } } } });这样前端代码里请求地址直接写/api/inbound/create开发环境下Vite自动代理到http://localhost:5000/inbound/create。前端代码不用写完整域名生产环境环境通过Nginx做类似代理前端代码一行都不用改。代码里有个容易踩的坑changeOrigin必须设为true。不设置时后端接受到的请求头Host还是localhost:5173某些后端框架对域名校验严格的话就会拒请求。我第一次联调时这就卡了半小时。4.2 生产环境部署不同方案的优缺点生产部署是我这次最想重点分享的部分。前后端分离的部署本质上是静态资源交给Web服务器API请求转发给后端进程。我先后尝试了两种方案最后混合使用。第一种方案是前端构建后交给IIS托管同时用URL Rewrite模块做反向代理。核心是web.config里的配置configuration system.webServer rewrite rules rule namevue-history-route stopProcessingtrue match url.* / conditions logicalGroupingMatchAll add input{REQUEST_FILENAME} matchTypeIsFile negatetrue / add input{REQUEST_FILENAME} matchTypeIsDirectory negatetrue / /conditions action typeRewrite url/index.html / /rule rule nameapi-proxy stopProcessingtrue match url^api/(.*) / action typeRewrite urlhttp://localhost:5000/{R:1} / /rule /rules /rewrite /system.webServer /configuration这个配置解决两个问题Vue Router的history模式刷新页面时会404所以把所有非文件请求一律重写到index.html和后端接口通信需要把/api/开头的请求转发到后端。第二种方案是纯Nginx部署前端构建后放在/usr/share/nginx/htmlNginx配置中做同样的history回退和API代理。Nginx的部署方式更轻量对服务器资源占用小适合Linux服务器上部署的场景。建议网络条件复杂的公司内网优先用IIS方案和Windows域环境集成比较方便独立部署在公网服务器就用Nginx性能和灵活性更优。5. 常见问题与部署避坑记录5.1 前端Token过期后的体验优化这个坑我印象特别深。最初Token过期后用户正在填表突然点击保存时弹出登录已过期然后被强制踢到登录页填了一半的数据全丢了。这在仓库现场使用中几乎是灾难级的体验。我后来的优化思路是Token设置8小时过期在有效期内用户在页面操作用不到重新登录同时记录Token获取的时间戳。在路由守卫中每隔一段时间检查Token剩余有效期如果低于30分钟就静默调用刷新Token接口替换本地存储的旧Token。用户全程无感知不用中断操作。如果刷新Token接口也失败说明用户确实登录太久了。此时不直接跳转而是弹出一个可以保存草稿并重新登录的提示框用户确认后把当前表单数据存到localStorage再跳登录页。这个改动后来在客户现场反馈特别好。5.2 数据库并发导致库存异常的解决办法多用户同时操作时库存扣减经常发生超卖问题。我遇到的具体场景是用户A和用户B同时看到库存剩10件A提交出库8件B也提交出库8件两个请求同时通过了库存充足的判断结果库存被扣成了负数。这个问题光靠事务的默认隔离级别解决不了我用的是乐观锁方案库存表中加一个Version字段更新时不仅检查库存数量还要检查版本号是否和查询时一致。var stock await _context.Stocks .FirstOrDefaultAsync(s s.MaterialId materialId s.WarehouseId warehouseId); // 检查库存是否足够 if (stock.Quantity quantity) return ResultDto.Fail(库存不足); var rows await _context.Database.ExecuteSqlRawAsync( UPDATE Stock SET Quantity Quantity - {0}, Version Version 1 WHERE Id {1} AND Version {2}, quantity, stock.Id, stock.Version); if (rows 0) return ResultDto.Fail(库存已被其他操作修改请刷新后重试);利用EF Core的ExecuteSqlRaw执行原生更新用版本号做冲突检测影响行数为0说明数据被其他操作修改过。这条语句能保证原子性同时利用数据库行锁防止并发问题。类似的方案后来也应用在锁定库存和释放库存上。5.3 EF Core性能优化避免N1查询后端开发里最容易被忽视的性能问题是EF Core的N1查询。典型场景是查询入库单列表时主表一条记录代码里循环读取明细和物料名称数据量到几千条时接口直接卡死。我后来统一用Include或ProjectTo来优化var orders await _context.InboundOrders .Include(o o.Items) .ThenInclude(i i.Material) .Where(o o.CreatedAt startDate o.CreatedAt endDate) .OrderByDescending(o o.CreatedAt) .Select(o new InboundOrderListDto { Id o.Id, OrderNo o.OrderNo, SupplierName o.Supplier.SupplierName, ItemCount o.Items.Count, TotalAmount o.Items.Sum(i i.Quantity * i.Price) }) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .ToListAsync();EF Core的延迟加载是个陷阱框架看起来好用但业务复杂后每条子查询都拖垮性能。我建议对列表查询一律用即时加载或投影确保生成一条SQL语句。也可以用SQL日志记录功能把EF生成的SQL打印出来逐条分析是否有多余查询。5.4 前端构建部署后的静态资源缓存问题部署Vue项目后出现过一个状况界面更新了但用户浏览器还是显示旧版本。这是因为服务器对静态文件设置了强缓存浏览器直接用了本地缓存完全没发请求。解决方案有两步第一步Vite构建时开启文件指纹默认已经开了文件名带哈希值第二步服务器设置缓存策略时对带哈希的文件设置缓存永久有效对index.html设置no-cache。Nginx下的配置写法location /assets/ { expires 1y; add_header Cache-Control public, immutable; } location / { add_header Cache-Control no-cache; try_files $uri $uri/ /index.html; }这样带哈希的文件每次更新后文件名变更浏览器自然请求新文件index.html每次都重新验证保证能拿到最新的入口文件。实际部署时还有个小技巧发布前清一下Nginx缓存目录避免旧文件残留。5.5 部署常见错误速查表结合自己经历和帮朋友排查的case汇总几条高频错误错误现象原因解决方法前端页面刷新后404Vue Router history模式未配置回退配置IIS URL Rewrite或Nginx try_files接口返回404前端代理路径与后端路由不一致检查代理rewrite规则是否正确Token验证一直失败签发和验证的密钥不一致检查配置文件Jwt:Key是否一致密钥长度需≥16字符跨域报CORS错误前端代理未生效或生产环境少了代理层确认代理配置生产环境用Nginx反代数据库字段精度丢失EF Core默认decimal精度18,2Framework配置HasPrecision指定精度这些问题的共同点是解决方案不复杂但排查看不到底层逻辑就会浪费很长时间。我通常建议部署前后先画一张部署架构图明确每个请求的完整路径再逐段排查效率会高很多。6. 项目扩展与二次开发建议6.1 系统功能的横向扩展方向这套仓库管理系统的核心功能已经跑通但实际落地到企业环境时通常还需要做一些扩展。我建议优先考虑这几个方向多仓库多货位的精细化管理在现有Warehouse表基础上增加货位表库存记录精确到货位级别这对仓库拣货和盘点很有价值条码扫描支持配合PDA或者手机摄像头入出库时直接扫条码录入效率提升非常明显对接上游ERP系统通过Web API或者消息队列同步物料档案和单据数据。扩展时要注意保持现有的单据驱动、流水可追溯的设计理念。很多系统改着改着就开始直接改库存、跳过单据短期看省事长期看后患无穷。我做过的一次二次开发就是客户要求做一个库存调整功能我坚持把这个功能也做成标准单据流程后续对账查数据时省了不少力气。6.2 性能优化和监控配置仓库系统在数据量增长后性能和监控是关键。我在这里做了三件事第一给核心查询表加上复合索引比如库存流水表上的(MaterialId, CreatedAt)索引列表中高频筛选字段都建了索引第二后端启用响应压缩中间件JSON响应体量直接减少60%以上对弱网环境尤其友好第三接入Sentry做前端错误监控以及Serilog做后端日志记录出了问题能快速定位到具体请求和堆栈。监控这块的建议是物料和库存相关接口的日志必须包括操作人、操作时间和变更前后数据因为一旦业务数据出问题要能倒查是谁什么时候改的。这一步在仓库系统里不只是技术支持还是财务审计层面的要求。6.3 移动端适配与PDA手持终端仓库作业中操作员经常要推着车、搬着货在电脑上操作很不方便。移动端适配是仓库管理系统落地时的加分项。我的做法是把核心作业页面入库、出库、盘点做成响应式布局用Vant组件库做移动端适配。由于前后端分离接口层完全不用改只是前端多了一套移动端页面入口。如果现场有条件用手持PDA可以用WebView套壳方案把移动端页面包装成PDA应用。条码枪这类设备一般都支持扫描后模拟键盘输入聚焦到输入框后扫码内容自动输入然后用回车或Tab键触发查询这套交互在Vue里实现成本很低但现场体验提升非常大。7. 写在最后的实操心得做这套仓库管理系统前后花了将近两个月最大的体会是前后端分离架构的价值不在于技术新而在于让团队协作和系统扩展变得干净。后端只操心业务逻辑和数据处理前端只关心交互和展示接口对清楚了两边基本可以并行开发不互相卡脖子。我在实际开发中踩到最深的坑一个是JWT密钥长度导致部署后认证失败另一个是EF Core延迟加载在数据量上来后的性能灾难。这两个问题如果能在设计阶段就规避后面能省下大量排查时间。最后再分享一个小技巧前后端联调时强烈建议把Postman或者Apifox的接口环境配置好把所有接口按模块分好目录。我用的流程是后端写完一个控制器就更新接口文档和测试用例前端联调时直接导入测试集合效率比一边开发一边联调高很多。这套项目本身就是一个完整的起点里面的设计模式、目录结构、错误处理方式都可以直接复用希望你能在这个基础上做出更适合自己业务的版本。本文还有配套的精品资源点击获取
返回列表