资讯动态

SpringBoot+Vue+MySQL在线招投标系统毕业设计全流程实战指南

发布时间:2026/10/19 9:15:58 来源:尧图企业网站定制
每年毕业设计的题目清单里“在线招投标系统”几乎是稳定出现的面孔。这个题目的经典之处在于它不冷门、不缺业务场景、难点可控而且 SpringBoot Vue MySQL 这套组合本身就是不少同学简历里反复出现的技能栈。如果你正在纠结毕业设计选什么题或者手里已经有一套这类系统的源码、数据库脚本、论文和部署文档却不知道从哪儿看起那我这篇就按实际做项目的顺序把从选题、数据库设计到后端、前端、论文和部署的完整链路捋一遍。我先说结论招投标系统能不能做好不取决于你用了多少炫酷的前沿技术而取决于你能否把“招标—投标—开标—评标—中标”这条业务链路讲清楚并且用代码把每一个状态的流转、每一次权限的判断都落到位。系统本身可以做得像一个演示级产品但业务逻辑必须是完整的、自洽的。下面就从为什么选这个题目开始讲起。1. 为什么“在线招投标系统”是毕业设计清单里的常青树1.1 这个题目到底在解决什么问题很多同学第一眼看到“在线招投标”会觉得雾里看花以为它是一个偏政府或大型企业才会用的系统。其实剥开外壳它做的事情很朴素招标方发布一个采购需求符合条件的投标方在截止时间前提交方案和报价最终按事先设定的规则选出最合适的合作对象。传统线下模式下公告难查、文件难管、评审过程不透明、结果容易让人质疑。在线化之后整个流程搬到网页上所有动作都留痕谁在什么时间传了什么文件、评了几分、最后选了谁一目了然。放到毕业设计里这等于给你提供了一个自带业务逻辑的完整场景。用户角色不止一个权限必须区分核心数据不止一张表项目、公告、投标文件、评审记录互相之间有关系流程不是简单的增删改查而是从草稿到发布、截止、评审、定标的连续状态迁移。毕业设计最怕的就是“功能做了很多但看不出到底解决了什么问题”而招投标系统的价值恰恰一眼就能看出来。1.2 为什么它适合当毕业设计题目这个题目被无数人选不是因为它简单而是它“难易适中、可攻可守”。上手做你可以只做招标方和投标方两个角色功能集中在公告发布、投标文件上传和结果公示想做得更有竞争力再加入管理员、评标专家角色增加评标打分、过程审计、统计报表等模块。从技术展示的角度看它几乎把 Web 开发的核心技术点都覆盖了登录注册和 Token 认证对应权限控制项目、公告的增删改查对应常规 CRUD投标文件的上传和下载对应文件处理与静态资源访问评标打分、结果汇总对应事务处理和聚合计算如果再做一两个图表页面还顺带覆盖了前端数据可视化。从论文写作的角度看它的“问题—需求—设计—实现—测试”这条线索特别清晰不像某些纯工具类项目写着写着就把论文变成了说明书。答辩时老师也容易提问而这些问题基本都围绕业务规则展开比如“投标截止后能不能再提交”“专家能不能看到投标人名称”“同一家公司能不能重复投同一个标”话一出口就能看出你是真写过代码还是只会照搬截图。1.3 做之前先给功能范围“画个圈”我见过不少同学做这个题最后栽在“什么功能都想加”。今天想加在线支付保证金明天想加短信通知后天想加实时聊天结果核心链路没做扎实附加功能也半途而废。毕业设计不是商业产品初版不需要覆盖所有现实规则但凡是做了的功能就要做得完整。下面这套功能边界是我比较推荐给初版实现的也是很多开源项目包的常见划分功能模块具体内容是否建议初版实现用户与权限登录、注册、用户管理、角色区分必须招标项目管理项目创建、编辑、发布、截止必须公告管理公告发布、列表、详情必须投标管理投标文件上传、报价填写、列表查看必须评标管理专家评分、分数汇总、评语记录强烈建议中标公示定标、公示结果、流标处理建议统计看板项目数量、投标情况图表可选支付与保证金在线支付、退款流程不推荐初版做支付模块涉及的需求边界太复杂动不动就要引入第三方支付环境的调试不是不能做而是会占用你大量调 Bug 的时间。如果指导老师没特别要求初版先把上面表格里“必须”和“强烈建议”的模块做完余力再往上加东西。2. 技术选型不是追流行而是让每个组件都各司其职2.1 后端选择 SpringBoot 的理由招投标系统本质上是“围绕一个业务流做大量状态处理和文件流转”的系统后端需要一个能快速写接口、方便管理依赖、社区资料充足的框架。SpringBoot 正好符合这几点。用 SpringBoot 最直接的优势是省去繁琐配置。过去用 SpringMVC 搭一个 Web 项目要写一堆 XML而现在一个启动类、几个注解就完事。配合 Maven 或 Gradle 管理依赖引入 MyBatis-Plus、JWT、文件处理等库都非常方便。对毕业设计来说框架本身不应该是主角业务逻辑才是所以“开发效率高”比“框架细节多”更重要。这里也顺带说一个常见选择认证和权限控制到底用 Spring Security 还是自己写拦截器我的建议是如果你的基础一般或者论文答辩时并不打算在权限框架上深入发挥那就用 JWT 拦截器 自定义注解的方式。原因是毕业设计最重要的目的是把业务流程说清楚自己写拦截器反而能展示你对 Token 校验、角色判断、接口保护这些问题的理解。用 Spring Security 也不是不行但配置链路较长一旦遇到权限不符合预期的问题初学者很容易卡在里面出不来。2.2 前端选择 Vue 的核心考虑Vue 这几年几乎成了中小型后台系统的默认前端选择。它能火不是因为“大家都在用”而是它的学习曲线相对平缓单文件组件写法直观模板语法贴近 HTML响应式数据模型容易理解。招投标系统的大部分界面是典型的“信息列表 表单填写 状态展示”Vue 的组件化在这种场景下非常舒服。具体版本上不做特殊要求的情况下我更推荐 Vue 3 Vite Element Plus 的组合。Vite 的启动速度很快开发体验好Element Plus 的表单、表格、上传组件能直接把前端工作量压得很低。如果你还是习惯 Vue 2 的写法也不是不行但多数通用模板和新项目已经转向 Vue 3从这里起步会少走很多老路。招投标系统前端有两个设计重点一是不同角色看到的内容和操作按钮完全不同二是所有流程节点都要有清晰的状态反馈。Vue 的动态路由和组件条件渲染恰好是解决这两个问题的顺手工具。2.3 为什么数据库必须选 MySQL在线招投标系统有明确的关系型数据模型用户、项目、公告、投标记录、评标记录、附件表彼此之间的关联复杂且牢固。这类场景用 MySQL 是又稳又省事的选择。MySQL 免费、跨平台、文档多5.7 和 8.0 两个版本都足够撑起毕业设计的体量基本不会有性能问题。有人会问“要不要上 Redis 做缓存要不要用 MongoDB 存附件信息”做毕业设计我不建议主动引入这些。一个项目正常的访问量之下MySQL 完全够用。缓存和非关系型数据库的引入会让部署环境变复杂也会让论文写起来更难抓住重点。趋势是好的但技术要和业务体量匹配。2.4 成熟的开发环境版本建议如果照着传统套路搭环境我建议用下面这套组合兼容性比较稳妥组件版本建议JDK1.8 或 11Maven3.6.x 及以上MySQL5.7 或 8.0Node.js16.x 或 18.xIDE后端 IDEA前端 VS Code 均可以有一点要特别注意MySQL 8.0 和 5.7 在连接驱动、时区配置上有差异。如果你拿到的数据库脚本或部署文档是按照 5.7 写的而本地装的是 8.0启动时很可能会报时区或驱动类错误。解决办法也不复杂要么把连接串里的时区参数改成serverTimezoneAsia/Shanghai要么换成项目文档指定的版本。这类环境坑在毕业设计阶段太常见了但也很不值得浪费一整天去排查。3. 数据库设计决定系统能走多远从角色权限到状态流转3.1 角色与权限的最小设计招投标系统至少涉及三类角色管理员负责系统维护和基础数据管理招标方负责创建项目、发布公告、发起评标投标方负责浏览公告、提交投标文件、查看中标结果。如果你还想体现评标过程的专业性与独立性就再增加一个评标专家角色专家只参与打分不能修改项目信息。在表结构上最简单也最好理解的做法是用户表里直接放角色字段不单独建复杂的角色-权限关联表。对毕业设计来说一个role_type字段就够用了取值分别是1-管理员、2-招标方、3-投标方、4-评标专家。这样在后端写权限判断时只需要比较当前登录用户角色的接口方法就能控制代码可读性很高。3.2 核心业务表到底要建几张一套比较完整的在线招投标系统数据库脚本通常包含下面这些核心表表名作用关键字段user用户基本信息username, password, real_name, role_typeproject招投标项目主表project_code, project_name, budget, owner_id, statusnotice招标公告project_id, title, content, attachment_idbid_record投标记录project_id, supplier_id, file_url, bid_price, statusevaluate_record评标打分记录project_id, bid_record_id, expert_id, score, commentattachment通用附件表biz_type, biz_id, file_name, file_url, file_size项目表、投标记录表、评标记录表是三条主干公告和附件围绕它们服务。我见过有些初学者把文件上传路径塞进业务表里直接写一个file_url字段这样做初看直接但后续如果一条投标记录需要同时上传技术标、商务标、资质文件三份就不得不再加三个字段非常不好扩展。用一张通用的attachment表通过“业务模块 业务记录 ID”来关联任何一张业务表的数据是最稳的做法。用户表和项目表之间要有一个外键逻辑project.owner_id指向user.id表示这个项目是哪个招标方创建的。投标记录里supplier_id指向用户表的投标方project_id指向项目表。有这些关系前端展示“我投过的标”“我发布的项目”时才不需要写复杂的中间表来支持。3.3 状态流转才是系统的业务灵魂招投标系统里最值得在论文和数据表里强调的是状态机设计。一个项目从被创建到最终完成不是一条直线而是根据业务操作不断往前推进的草稿→已发布→投标截止→评标中→已定标/流标对应到数据库我习惯用一个status字段存整数。0 表示草稿1 表示已发布2 表示已截止3 表示评标中4 表示已定标5 表示流标。发布公告的操作把状态从 0 改成 1投标截止时间到了以后把状态从 1 改成 2管理员或招标方创建评标任务后进入 3评标结束、结果确认后进入 4。如果在投标截止后没有一家有效的投标记录就把项目标记为 5走流标流程。为了让这套状态逻辑不散落在代码的各个角落建议在后端定义一个枚举类或者常量类统一定义状态值前端对应维护一套状态字典。否则前端显示“已关闭”后端叫“截止”数据库里是数字 2对不上号的时候排查问题会特别痛苦。3.4 索引、时间字段和逻辑删除数据库脚本虽然只是项目的一句话但写得好不好拿到手上跑一遍就看得出来。有两类细节是我强烈建议注意的。一是索引。project_code应该建唯一索引因为项目编码不能重复bid_record.project_id、evaluate_record.project_id这类经常出现在 where 条件里的外键字段要建普通索引。索引不过度设计但主查询路径上必须有不然等到数据量测试阶段会发现列表加载变慢。二是时间字段和删除字段。创建时间create_time默认值可以直接写成CURRENT_TIMESTAMP更新时间update_time可以在代码层统一维护业务表建议增加deleted逻辑删除字段用 0 和 1 标记删除状态。这样用户误删项目、撤回投标时数据还有恢复余地论文里也可以写一笔“系统采用逻辑删除保证数据可追溯”这在招投标业务里是很自然的合规需求。4. 后端实现SpringBoot 分层结构与核心业务点4.1 分层架构怎么分才对后端工程结构我建议直接按标准方式分层不要把所有业务逻辑全堆在 Controller 里。一个通用的目录结构大概长这样com.example.bidding ├── controller // 接收请求返回统一响应 ├── service // 业务逻辑状态流转、数据校验 ├── mapper // 数据库访问 ├── entity // 数据库表对应的实体类 ├── dto // 前端传参的数据对象 ├── common // 统一响应、异常处理、常量 ├── config // 跨域、拦截器等配置 └── utils // 工具类比如 JWT 处理Controller 层要做的事情是接收参数、调用 Service、返回结果不直接操作数据库Service 层承载业务规则比如“投标截止后禁止提交”“同一投标人对同一项目只能提交一次”Mapper 层做最基础的增删改查。这样划分的好处之一是论文好写需求分析、概要设计、详细设计能顺着模块写好处之二是答辩的时候老师问“这个状态是怎么改的”你可以直接定位到 Service 层的对应方法。4.2 登录认证与权限控制的落地登录接口大体上是同一个模板接收用户名密码查询用户校验密码生成 Token返回前端。这里密码存储一定要用加密方式不要明文存库。BCrypt 是常见选择Spring Security 里可以直接用BCryptPasswordEncoder不想引入完整 Spring Security 的话也可以单独引入 spring-security-crypto 这个小而美的依赖。Token 校验用拦截器实现大致流程是前端在请求头里带Authorization拦截器读取 Token解析出用户 ID 和角色放到当前请求上下文后端在需要特定角色的接口上加上自己定义的角色注解拦截器发现当前用户角色不匹配时直接返回 403。核心代码的风格大致像下面这样Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (handler instanceof HandlerMethod) { HandlerMethod hm (HandlerMethod) handler; RequireRole requireRole hm.getMethodAnnotation(RequireRole.class); if (requireRole null) { return true; } String token request.getHeader(Authorization); // 解析 token校验用户角色 if (!userTokenService.checkRole(token, requireRole.value())) { throw new BiddingException(无权访问该接口); } } return true; } }这段代码是示意不是让你抄完就能跑。但它体现了一个重要思路前端菜单可以按角色隐藏按钮但后端的每个敏感接口必须自己再做一次角色校验。只靠前端隐藏按钮的权限系统在答辩演示时一旦被老师抓到直接调接口绕过权限就很尴尬。4.3 投标文件上传、下载与存储投标文件是这个系统的核心资产。上传接口要注意四件事文件大小限制、文件扩展名校验、存储目录划分、文件重名处理。我的建议是在后端配置里写一个upload.path文件按/项目ID/供应商ID_时间戳_原文件名这个规则落盘。这样不同项目的文件天然隔离不同供应商的文件一眼能区分。数据库的attachment表里存相对路径不要存C:\xxx或/root/xxx这类绝对路径因为项目部署到不同环境时路径一换就会出问题。文件预览的场景在校内演示时经常出现。如果只是展示“我有这个功能”最省事的做法是提供一个下载接口前端用文件流方式接收。想要在线预览 PDF 或图片后端返回文件流时把Content-Type设对前端再配合新窗口打开即可。不要试图把整个 PDF 转成 base64 塞进 JSON 返回数据量大且速度很慢。4.4 评标打分的批量提交与事务处理评标模块是整个系统里最值得写进论文的后端逻辑。典型场景是一个项目有多家投标方每个专家登录系统后需要对每一家投标方按几个维度打分比如技术分、商务分、资质分最后把这些分数汇总成总分再按总分排序确定中标候选人。这个功能最容易出的问题是“半成功”专家提交了 5 家评分前 3 条更新成功第 4 条因为数据格式问题失败最后界面提示失败但数据库已经改了一半。解决办法是给这个提交过程加上事务控制。在 SpringBoot 里只需要在 Service 层方法上标注Transactional方法内任意一步抛异常数据库就会整体回滚。还有一个业务细节容易被忽略同一专家不能对同一家投标方重复提交否则评标结果可以被恶意篡改。最简单的方式是给evaluate_record表加上(project_id, bid_record_id, expert_id)联合唯一索引。这是数据库层面的兜底比在代码里先查再插稳得多。4.5 后端最容易踩的几个坑这套项目做下来后端常见的坑集中在这几个位置。跨域问题基本人人都会遇到。前端跑在 5173后端跑在 8080端口不同就触发跨域。解决办法是在后端加一个允许跨域的配置类或者写一个CrossOrigin注解挂在 Controller 上。如果用了拦截器还要注意跨域预检请求OPTIONS不能被拦截器拦掉否则前端请求会一直失败。时间格式问题也很典型。数据库存的是2025-01-01 10:00:00返回给前端变成一串数组或英文格式页面显示很难看。解决办法是统一配置 Jackson 的日期格式或者在后端 DTO 的日期字段上标注JsonFormat(pattern yyyy-MM-dd HH:mm:ss)。文件上传大小限制也值得提前配置。不修改配置的情况下SpringBoot 默认允许的单文件大小常常不够用企业标书动辄十几兆甚至几十兆。建议在后端配置文件里把spring.servlet.multipart.max-file-size和max-request-size调大一些并在前端上传组件里做同样的限制两边保持一致。5. 前端实现Vue 如何把复杂流程变成好操作5.1 路由与菜单按角色动态生成前端要做的事情不复杂但很容易写成一堆页面堆在那里。更好的做法是先站在用户角度想招标方登录后想看到“我发布的项目”投标方登录后想看到“正在招标的项目”专家登录后想看到“待评标的项目”。这三种用户进入首页看到的内容完全不一样。对应在代码里如果用的是静态路由可以在路由表里给每个菜单配置roles字段如果是动态路由则在用户登录后根据role_type过滤路由并加入菜单。推荐简单做法后端登录接口返回用户角色前端在路由的beforeEach钩子里判断当前路由是否允许当前角色访问不允许就跳到对应角色的默认首页。这样菜单和页面都干净。5.2 核心页面与组件怎么拆常见的页面分解方式是这样的页面核心交互项目列表页状态筛选、分页、创建/发布按钮项目详情页展示项目信息、公告 Tabs、投标列表投标提交页上传文件、填写价格、确认提交评标打分页每家投标方一个评分表单提交后汇总结果公示页表格展示中标候选人状态标签醒目组件拆分上不要把整页逻辑全塞进一个巨大文件里。项目列表页至少拆成搜索条件组件、表格组件、分页组件文件上传在多个页面都有应该抽成一个公共的上传组件接收接口地址和大小限制返回上传成功的文件路径。这样页面代码短、复用性好、后期改样式也不至于牵一发动全身。5.3 axios 封装带来的开发效率提升前端和后端交互我强烈建议不要在每个页面上裸写几十遍axios.get。先封装一个统一的request.js做三件事设置baseURL自动带上 Token 请求头统一处理后端返回的错误码。一个比较精简的封装思路如下import axios from axios import { ElMessage } from element-plus const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) request.interceptors.response.use( res { if (res.data.code 200) { return res.data.data } ElMessage.error(res.data.message || 请求失败) return Promise.reject(new Error(res.data.message)) }, error { if (error.response error.response.status 401) { localStorage.removeItem(token) window.location.href /login } ElMessage.error(网络异常请稍后重试) return Promise.reject(error) } ) export default request封装之后页面里只需要const list await getProjectList(params)就能拿到业务数据不用在每个页面处理错误弹窗和 401 跳转。这个细节看着小但在答辩演示时一次请求失败后自动跳登录、一次未授权提示都会让老师觉得系统做得比较完整。5.4 文件上传与状态反馈的交互设计文件上传组件最好做到“选了文件先本地预览上传成功后替换成文件链接”同时显示上传进度条。很多同学做上传功能时文件传到一半没有反馈、上传成功后列表又不刷新用户很容易误以为提交失败了。在投标场景里这个体验尤其致命。前端在上传前做两件事校验文件类型和大小给用户及时提示上传成功后把后端返回的file_url暂时存到表单数据里等到整个投标表单提交时再一并发给后端。这样避免“文件传上去了但业务记录还没创建”的半成品状态。5.5 几个容易被忽略的前端细节第一个是表格的 loading 状态。接口没返回之前表格区域要有加载动画否则用户反复点按钮就会发出很多重复请求。第二个是按钮的状态控制。项目还是草稿状态时不能显示“投标”按钮投标已经截止时“提交投标”按钮应该置灰评标结束后评分表单应该只读。这些判断都要围绕状态字段做不要硬编码在页面里。第三个是倒计时展示。投标截止时间距现在还剩多少时间直接用截止时间减去当前时间前端每秒更新一次能够让页面显得更真实。实现上写一个公共的countdown方法就行。6. 论文、数据库脚本和部署文档如何让项目变成一套可交付成果6.1 论文各章怎么写得有逻辑系统做完了论文是让成果真正落地的一步。很多人写论文时把源码里的代码大段贴进去这是最不推荐的做法。论文要回答的问题不是“代码怎么写的”而是“为什么要这样设计”。一个比较稳妥的结构是绪论写招投标的背景、系统开发的意义、国内外研究现状相关技术介绍介绍 SpringBoot、Vue、MySQL但不要变成百科搬运要结合本系统的场景说明“为什么选这套组合”需求分析画用例图、描述功能需求和非功能需求系统设计给出总体架构图、功能模块图、数据库 ER 图这张图要好好做老师经常会瞄一眼看你的表关系是否成立系统实现按角色或模块展示核心界面截图配合关键代码和讲解系统测试写测试用例表包括测试目标、输入数据、预期结果、实际结果总结与展望说自己做了哪些工作还存在哪些不足未来可以怎么扩展。数据库设计部分建议用独立的表格说明每张表的字段含义而不是只扔一个建表 SQL 到附录里。字段名、类型、约束、说明写清楚导师印象分会高不少。6.2 数据库脚本和初始化数据的重要性“源码数据库论文部署文档”里的数据库不应该只是建表 SQL还应该包含基础初始化数据。实际交付时我建议按这几类组织脚本schema.sql建库、建表语句data.sql初始化管理员账号、基础字典数据、演示项目和几条投标记录README文档里要写清楚执行顺序和默认账号密码。初始化数据极其重要。如果评委或老师拿到项目后登录进去看到空荡荡的界面没有项目、没有投标记录就很难判断系统跑起来是什么效果。预先造好两三笔状态不同的演示数据比如一个已发布的招标项目、一个投标截止的项目、一个已经定标的项目演示时就可以直接切不同项目展示不同流程阶段非常加分。6.3 部署文档要写清楚的可复现步骤最差的部署文档是“看一下项目的 README 就会了”这种话。好的部署文档应该让一个从没接触过项目的人照着做能在半小时内把系统跑起来。一个值得参考的步骤结构是环境准备列出 JDK、Maven、MySQL、Node.js 的版本要求初始化数据库使用某数据库客户端导入schema.sql和data.sql修改后端配置在application.yml里改数据库账号、密码、文件上传路径启动后端用 IDEA 打开后端工程等待依赖下载运行启动类安装前端依赖在前端目录执行npm install启动前端执行npm run dev浏览器访问给出的地址。这里特别提醒一点后端配置里的数据库密码不要写成root/123456就以为完事了部署文档里要说明“如果你的本地密码不同请同步修改 application.yml”。很多同学拿到项目后第一步就会卡在数据库连不上一半以上是密码不一致引起的。文档里把这个步骤写醒目一点能省无数答疑时间。6.4 答辩演示顺序与常见提问准备答辩演示时不要从头像、用户管理这些基础页面开始播而是从一个具体业务场景切入。推荐的演示路径是用管理员账号登录进入系统展示角色管理、数据统计切换到招标方账号创建一个新项目并发布公告切换到投标方账号浏览公告并提交一份投标文件切换回招标方账号查看已收到的投标文件切换到专家账号为几家投标方案打分回到招标方账号发布中标结果。这条路径正好把整个状态流转走了一遍每一步都有页面切换和数据显示观众能直观理解系统做了什么。答辩时老师常问的问题无外乎这几类为什么用 JWT 不用 Session同一个投标方重复投同一个标你怎么防投标截止后还能不能提交评标分数怎么保证不被人为篡改。其实答案都在代码里比如联合唯一索引、事务、状态字段判断。提前把这些问题对应的代码位置在 IDE 里标好演示时能直接点开给老师看效果比空口解释好很多。写在最后的一点实际操作体会我在帮人做这个方向的项目时最深的感触是真正拉开毕业设计质量差距的往往不是功能数量而是“业务闭环能不能跑通、数据关系是不是清晰、文档步骤能不能复现”。功能堆得再多如果投标文件传不上去、状态改了页面不刷新、部署文档照做却起不来一切努力都会在演示时打折扣。所以我建议不管你手里拿到的是自己做的系统还是别人整理的项目包动手改功能之前先干三件事第一把数据库脚本完整跑一遍看所有表和初始化数据是否正常第二把整条“招标—投标—评标—定标”流程从前端界面走一遍确认状态流转没有断点第三把部署文档从头到尾照着执行一次记录下所有和预期不符的地方。这三件事做完你对项目的理解深度会超过大多数人答辩时的底气也会完全不同。做技术的都知道跑通一个流程不算本事能在任何一台新电脑上快速复现它才叫真明白。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑