
很多计算机专业的同学在选课程设计或毕业设计题目时都会碰到“宠物店管理系统”这种经典选题。说实话这类题目看起来简单但真正要把一套基于Vue的前端、配套的后端接口、MySQL数据库全部打通再完成调试部署和万字论文工作量一点都不比一个花哨的App小。我最近刚带一个学弟完整跑完这个项目从环境配置到部署上线用了大概两周过程中踩了不少坑也积累了一套可以直接复用的流程。这篇就把整个项目从需求拆解、技术选型、数据库设计、环境配置、编码联调到部署上线完整地过一遍。无论你是刚学完Vue想做实战项目的学生还是被“程序源码数据库调试部署开发环境配置”这种交付清单搞得一头雾水的初学者这篇都能帮你把思路理顺。我尽量按实际开发顺序来写而不是按论文目录来写因为真实项目里先搞清楚业务再选技术然后配置环境最后动手写代码才是最省事的路径。1. 宠物店管理系统到底要管什么先做需求拆解很多人拿到这个题目上来就建工程、写代码结果写了两周发现需求没想清楚表结构反复改前端页面推翻重来。我带的那个学弟第一次就是这么翻车的。所以第一步别急着敲键盘先把这个系统要解决的业务问题拆清楚。宠物店的核心业务大致分两条线。一条是商品销售宠物食品、玩具、药品、用品这类业务和普通进销存系统很像核心是商品管理、库存、订单收银。另一条是服务类业务宠物美容洗护、寄养、活体销售这类业务的特点是带有时间属性需要预约、状态流转和按服务项目或按天计费。一个完整的宠物店管理系统通常还要包含会员管理、宠物档案和基础数据统计。我把这个项目的功能模块整理成了一张表做需求分析的时候可以直接对着这张表拓展模块核心功能涉及数据表登录认证管理员/员工登录、退出、密码修改admin / employee宠物档案宠物新增、编辑、疫苗状态、健康备注pet顾客管理会员信息、等级、积分、消费记录customer商品管理商品分类、上下架、库存预警goods / category销售收银购物车、订单生成、结算、退货orders / order_item寄养服务寄养预约、入店登记、离店结算boarding美容预约服务项目预约、状态流转appoint数据统计销售额趋势、商品排行、会员增长基于订单聚合查询1.1 核心业务模块清单模块清单看起来简单但实际动手前必须做一次“需求减法”。我带学弟做的时候他一开始列了十几个模块连员工考勤、短信营销都加进去了我直接砍掉四个只保留上面这些。砍掉的核心逻辑有两个第一系统边界要贴合宠物店的实际运营场景。员工考勤不是不能做但它属于行政人事范畴加了之后和宠物业务的关联不强论文里的需求分析一章会变得很散。第二答辩时要能被老师追问而答得出来。功能越多越容易在细节上露怯比如“营销活动管理”涉及优惠券、满减规则、使用条件这些业务逻辑一旦展开复杂度远超一个课程设计的体量。所以这个项目的MVP最小可用版本就是登录、宠物档案、顾客管理、商品管理、订单收银、寄养服务、美容预约和数据统计。把这几块做深做透每一块都做到能演示、能讲解评分不会低。1.2 画好需求边界MVP优先在做需求分析的时候还要注意一个很容易被忽略的点很多功能看起来有“一整套设计”其实最有价值的是那几条核心业务逻辑。比如寄养费用计算是一个典型的“规则密集”场景。寄养按天计费超过晚上某个时间点算半天会员打八折多只宠物一起寄养可以再折上折。这些规则看起来烦琐但恰恰是系统里最容易出彩的地方。把费用计算逻辑用清晰的状态机实现把折扣规则做成可配置再在界面上把计算过程展示出来这一块就足够在论文的“系统设计”和“系统实现”两个章节里分别写上千字。同样的道理宠物档案里的疫苗状态跟踪也值得做好。一只宠物打没打疫苗、什么时候该打下一针这种信息在宠物店里比单纯记录“这是一只金毛”有价值得多。做需求拆解时多往业务细节上钻一钻后面写代码时你会发现自己对表结构的理解清晰很多。2. 技术选型Vue决定前端后端和数据库怎么搭标题既然是“基于Vue的宠物店管理系统”前端技术栈基本锁死是Vue生态。但真正动手时你会发现一个容易被忽视的问题是Vue 2和Vue 3的版本选择。2.1 前端技术栈版本对号入座目前主流方案是Vue 3 Vite Composition API配Element Plus组件库。Vue 2 Vue CLI Element UI属于上一代组合网上大量教程还在用但新项目再用它等于从第一天就在维护老代码。我在带项目时直接让学弟用Vue 3理由很简单官方推荐、生态活跃、遇到的报错能在最新文档和社区里找到答案。如果你跟着老教程走很容易出现“下载了Vue 3模板装的是Element UI页面白屏”的情况。Element UI从根本上不兼容Vue 3必须用Element Plus。这属于版本错配的经典坑。为了防呆建议在建项目前就确定版本组合不要“先用着再说”。前端另外两个标配是vue-router和pinia。路由负责页面跳转和权限拦截pinia负责全局状态管理比如保存登录之后的用户信息、购物车数据。网络请求统一用axios封装。2.2 后端推荐组合Spring Boot MyBatis-Plus MySQL后端我推荐Spring Boot 2.7 MyBatis-Plus MySQL 8.0这个组合适合大多数课程设计和毕业设计。选它的理由有三条第一能和你课程里学的Java知识衔接。论文里写“系统架构设计”一章时Spring Boot的分层思想、依赖注入、自动配置都是可以展开论述的点。第二MyBatis-Plus的BaseMapper已经把单表增删改查封装好了省掉大量重复的mapper代码一个后台管理系统大部分功能都是单表操作用它能省至少一半工作量。第三这套组合的网上资源最多从环境搭建到报错处理都有海量文章可查对初学者友好。如果你的Java基础确实薄弱用Node.js的Express或者Python的Flask做后端也行。技术上没有本质区别但在论文的“技术选型对比”部分Spring Boot能对比的维度明显更多比如MVC架构、自动配置、生态成熟度、事务管理等容易写出深度。2.3 前后端项目结构规范技术栈定了之后前后端的项目结构也要提前规划好。我常用的前端结构是这样frontend/ src/ api/ // 按模块封装的axios请求 router/ // 路由配置 store/ // pinia状态管理 views/ // 页面组件 components/ // 公共组件 utils/ // 工具函数 vite.config.js // 开发服务器及代理配置后端结构按Spring Boot标准分包backend/ controller/ // 接口层接收前端请求 service/ // 业务逻辑层 mapper/ // 数据访问层 entity/ // 实体类对应数据库表 config/ // 跨域、拦截器等配置 common/ // 统一返回结果、异常处理前后端分离项目最忌讳把axios请求写在组件里面接口调用散落在各个页面。规范做法是在api目录下按业务模块建文件比如pet.js里统一放宠物相关的所有接口页面里只是调用函数这样后期改接口前缀、加统一鉴权都方便。3. 开发环境配置最容易翻车的第一步开发环境配置是这个项目交付清单里的重要组成部分也确实是最容易劝退人的一步。我每次帮人看环境问题十次里有八次是版本不匹配或者path配错。下面按顺序写一遍完整流程照着做基本不会出大问题。3.1 完整配置步骤第一步安装Node.js。建议Node 16.18以上或者18.x LTS版本安装时勾选“Add to PATH”。装完打开终端输入node -v能打印版本号就说明Node本身没问题。第二步配置npm镜像。这一步能极大提升依赖安装速度。在终端执行一行命令npm config set registry https://registry.npmmirror.com之后用npm install装依赖速度会从“半天没反应”变成“几十秒搞定”。第三步用Vite创建前端项目。npm create vitelatest pet-shop-frontend -- --template vue cd pet-shop-frontend npm install npm install element-plus axios vue-router4 pinia npm run dev浏览器访问终端里提示的地址能看到Vite默认页面就说明前端骨架跑起来了。这一步不着急写业务先把“改代码→热更新”的闭环跑通。第四步配置后端环境。安装JDK 1.8或JDK 17、Maven 3.6以上IDE用IntelliJ IDEA。Spring Boot项目可以直接去start.spring.io生成依赖选择Spring Web和MyBatis相关组件。第五步安装MySQL 8.x客户端用Navicat或DBeaver都行。创建数据库时字符集选utf8mb4这一步直接决定后面中文数据会不会乱码。3.2 高频报错与处理配置过程中有几个常见报错提前有个心理准备可以少走弯路。npm install时报ERESOLVE错误大多是依赖版本冲突可以加--legacy-peer-deps参数绕过。Maven下载依赖慢在maven的conf/settings.xml里配置阿里云镜像源国内下载速度和墙内墙外完全是两个体验。Spring Boot项目启动失败先看启动日志最底下的Caused by百分之八十是MySQL连接配置不对检查application.yml里的url、用户名、密码是否匹配本机环境。后端默认8080端口被占用也是高频问题经常会提示Web server failed to start. Port 8080 was already in use。解决方式很简单改掉application.yml里的server.port换成8081或者别的未被占用的端口就行。我每次配环境都反复强调一句话不要急着写业务。先把一个最简单的页面跑通把Vite代理配好让前端能请求到后端接口确认这个链路通了再往后走。环境搭建阶段省下的时间迟早会在联调阶段加倍还回来。4. 数据库设计一张表一张表地敲定数据库设计是整个项目的核心直接决定后端代码复杂度、前端页面查询逻辑以及论文篇幅。很多人的表结构建得太随意一个表恨不得装下所有字段到写业务时才发现缺这个少那个来回改苦不堪言。4.1 核心表结构设计这个项目我建议至少建8张表管理员表、顾客表、宠物档案表、商品分类表、商品表、订单表、订单明细表、寄养记录表再加一张美容预约表。下面重点讲几张核心业务表的字段设计思路。宠物档案表是整个系统的灵魂字段建议这样设计CREATE TABLE pet ( pet_id INT PRIMARY KEY AUTO_INCREMENT, customer_id INT NOT NULL COMMENT 所属顾客ID, pet_name VARCHAR(50) NOT NULL, pet_type VARCHAR(20) COMMENT 猫/狗/其他, breed VARCHAR(50) COMMENT 品种, birthday DATE, weight DECIMAL(5,2), gender TINYINT COMMENT 0-公 1-母, vaccinate_status TINYINT DEFAULT 0 COMMENT 0-未接种 1-已接种, health_note VARCHAR(255) COMMENT 健康备注, create_time DATETIME, update_time DATETIME );字段都平平无奇但注意vaccinate_status和health_note。疫苗状态是宠物店服务的前置条件寄养、美容前都要检查宠物疫苗是否接种这个字段会在前后端多处被引用设计上要预留。health_note不固定长度不硬塞进一个枚举里因为每家店的病历写法都不一样。订单表采用“主表明细表”结构。主表存订单号、顾客ID、总金额、订单状态明细表存每个商品的数量、单价、小计。拆成两表后一个订单关联N个商品就不需要每条记录都重复存订单信息和顾客信息方便统计每个商品的销量。order_no要生成一个有业务含义的编号比如日期加随机数不要直接用自增主键当订单号因为页面上要展示、客户会念出来数字从1开始很容易被猜。寄养记录表的费用相关字段这样设计CREATE TABLE boarding ( boarding_id INT PRIMARY KEY AUTO_INCREMENT, pet_id INT NOT NULL, check_in_date DATETIME NOT NULL COMMENT 入店时间, check_out_date DATETIME COMMENT 离店时间, daily_price DECIMAL(10,2) NOT NULL COMMENT 日单价, discount DECIMAL(3,2) DEFAULT 1.00 COMMENT 折扣系数, total_fee DECIMAL(10,2) COMMENT 总费用, status TINYINT COMMENT 0-预约 1-在店 2-已结算 );total_fee不要设计成一个用户手工填的字段而应该由service层根据check_in_date、check_out_date和daily_price、discount自动计算后写入。寄养费怎么算、超时怎么算、会员折扣怎么叠加在service层写清晰这本身就是一个很好的论文素材。4.2 SQL脚本与测试数据准备建表时统一使用InnoDB引擎。很多课程设计要求必须加物理外键但实际开发中我建议用逻辑关联代替物理外键。外键会带来连锁删除和更新限制后台管理系统里直接用Python或Java代码控制关联逻辑更灵活。这个取舍在论文的“数据库设计”一节里专门写一段说明反而显得有思考。建完表之后把全部建表SQL保存成init.sql再准备一份insert.sql作为测试数据。测试数据的质量直接影响演示效果和论文截图。我建议至少准备3个管理员、5个员工、20个顾客、30只宠物、40个商品、10条订单、5条寄养记录、3条美容预约。有了这些数据前端分页控件才能体现翻页效果统计图表才有曲线可看。我常用的一个技巧是所有create_time字段用当前时间附近的日期错开模拟一周内的真实数据。这样做销售额趋势图表的时候柱状图不是一条直线看起来专业得多。5. 前端核心实现登录、路由守卫和宠物档案前端编码阶段我挑三个最能体现系统架构水平的部分细说路由设计、axios封装、宠物档案页面实现。这三个部分写好了其他模块基本是复制这个模式去套。5.1 路由与登录拦截路由设计决定整个系统的页面组织方式。登录页单独成一个路由系统内部页面统一嵌套在Layout布局下。关键代码如下import { createRouter, createWebHistory } from vue-router const routes [ { path: /login, component: () import(/views/Login.vue), meta: { title: 登录 } }, { path: /, component: () import(/layout/Layout.vue), redirect: /dashboard, children: [ { path: dashboard, component: () import(/views/Dashboard.vue), meta: { title: 数据统计, requireAuth: true } }, { path: pet, component: () import(/views/pet/PetList.vue), meta: { title: 宠物档案, requireAuth: true } } // 其他页面 ] } ] router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requireAuth !token) { next(/login) } else { next() } })这个全局前置守卫是登录拦截的推荐做法从localStorage取token没有token且目标页面需要登录时跳转到登录页。页面多的时候这种拦截写法比在每个页面里单独判断权限要优雅得多也方便后续扩展角色权限。5.2 axios封装与代理配置axios必须封装不能用一堆裸请求散落在组件里。我在api目录下建一个request.jsimport axios from axios import { ElMessage } from element-plus const request axios.create({ baseURL: /api, // 开发环境走代理 timeout: 10000 }) request.interceptors.response.use( response { const res response.data if (res.code 200) { return res } ElMessage.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) }, error { ElMessage.error(error.message || 网络异常) return Promise.reject(error) } ) export default request开发环境跨域问题用Vite代理解决。在vite.config.js里这样配server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }前端发出/api/pet/list请求Vite开发服务器把它转发到后端8080端口浏览器根本察觉不到跨域。这个方案比在后端写CrossOrigin注解干净得多生产环境部署时再把/api代理到Nginx反代的实际后端地址就行。5.3 宠物档案页面的重点宠物档案页面是一个典型CRUD页面表格展示、搜索、分页、新增弹窗、修改弹窗、删除确认。写这种页面时重点有三个。一是搜索条件和后端mapper的where条件要严格对齐。比如按宠物类型下拉筛选和按姓名模糊搜索前端查询参数名必须是petType和petName后端接口接收的参数名一致否则过滤条件静默失效页面看起来就像什么都没发生。二是分页参数统一用pageNum、pageSize后端用MyBatis-Plus的分页插件接收返回结构固定为total和records这样每个列表页都能复用同一套分页逻辑。三是宠物照片上传。照片文件不要直接存数据库而是将图片保存到服务端的upload目录数据库只存图片的相对路径或URL。这个设计虽然说起来很简单但真做起来很多初学者会直接塞base64字符串到数据库导致数据库体积爆炸。Element Plus的el-table和el-dialog组合是这类页面的主力代码模式非常固定照着官方文档写就顺关键是保持所有页面的交互一致列表在左边筛选右上角新增按钮操作列放编辑和删除。页面统一才能减少测试时的工作量。6. 后端接口设计与联调中的“隐形大坑”后端接口设计最重要的是统一返回格式。如果不统一每个接口各返回各的JSON形状前端每个页面都要单独处理数据结构联调时必然乱套。6.1 统一返回格式与异常处理我惯用一个Result类public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(success); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }所有Controller方法的返回值统一用Result包装。前端axios拦截器里根据code做统一处理业务请求在拿到res.data后直接用。再配合一个全局异常处理器比如参数校验失败统一返回500和提示信息后端代码会干净很多。6.2 联调期三座大山前后端联调阶段最容易出问题的是时间格式、数字精度和字段命名这三件事我几乎在每次带项目时都要反复强调。时间格式问题非常经典。后端用LocalDateTime返回数据默认序列化结果是“2024-12-18T10:30:00”前端显示到页面上会多出一个字母T既不美观也容易被用户误解。解决办法是在application.yml里统一配置Jackson的时间格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8金额字段在数据库用decimal类型Java实体里用BigDecimal对应。前端如果用浮点数直接显示可能变成很长的小数记得加toFixed(2)。另外BigDecimal比较大小不要用equals要用compareTo这是Java面试的经典坑但在系统开发里同样重要。字段命名问题集中在驼峰和下划线的转换。MySQL习惯用下划线命名比如create_timeJava实体习惯用驼峰createTime。MyBatis-Plus默认开启驼峰转换功能一般不需要额外配置但如果你从网上抄了老版本的配置导致转换没生效就会出现前端传customerId后端收到customer_id直接报空指针的现象。联调阶段把这三个问题提前在项目里统一处理掉后面所有模块的联调都会顺畅。我还建议在联调期间用Apifox或者直接在代码里加Swagger注解把每个接口的路径、参数、返回示例整理成文档。就算只是整理成一份markdown文档写论文“系统测试”章节的时候都会轻松很多。7. 调试部署实战从本地开发到上线运行调试部署是这个项目交付清单里和源码并列的重点。很多同学把代码写出来就跑完全没做过部署结果交上去的演示还是只能在本地起的开发服务器。这既影响最终评分也让自己失去一次完整的工程经验。7.1 开发环境调试流程开发环境下的标准流程是前端npm run dev跑Vite服务器后端IDEA直接运行主类数据库本机MySQL三者在开发机上跑通。准备开发环境时最需要注意的是application.yml里的数据库连接配置不能写死每台电脑的root密码都不同第一次运行前必须改成自己的。我见过太多第一次启动失败的案例原因就是配置文件里是别人的数据库地址和密码。另外MySQL 8.0和5.7的驱动路径不同8.0用com.mysql.cj.jdbc.Driver5.7用com.mysql.jdbc.Driverpom里引的mysql-connector-java版本要对得上。这个细节在启动日志里看不出来往往要等到第一个查询接口执行时才报错排查成本很高。7.2 生产部署实操如果部署到服务器或者交付给老师标准流程分四步。第一步后端打包。在backend目录执行mvn clean package -DskipTests打包完成后target目录下生成一个jar包。这个jar是Spring Boot的可执行jar里面内嵌了Tomcat直接运行就行。第二步前端打包。在frontend目录执行npm run build生成dist目录里面是纯静态文件。第三步前端静态文件交给Nginx托管后端jar包用java -jar命令运行。Nginx的server块配置大概是这样的server { listen 80; server_name localhost; root /usr/share/nginx/html/dist; index index.html; location /api/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }第四步把后端jar包用后台方式运行nohup java -jar pet-shop-backend.jar logs/app.log 21 日志重定向到logs目录方便之后排查问题。服务器防火墙需要放行80端口MySQL如果要远程访问还要额外开放3306但生产环境更稳妥的做法是让后端和数据库都在内网互通不要为了图省事把数据库直接暴露公网。7.3 history模式404问题部署阶段有一个经典问题是几乎所有用Vue的人都会遇到的Vue路由用history模式打包部署到Nginx之后首页能打开但刷新一个二级页面时直接404。原因是history模式下的URL是纯前端路由浏览器刷新时真的向服务器请求了这个路径而服务器上并不存在这个文件。解决方式就是Nginx配置里的那一行try_fileslocation / { try_files $uri $uri/ /index.html; }它的意思是请求路径如果找不到对应文件就回退到index.html由前端路由接管。这个配置加进去后刷新404的问题立刻消失。如果用的是Spring Boot直接托管前端静态文件也可以用类似的forward规则解决。部署完成后一定要做的事用浏览器无痕模式打开页面完整走一遍登录、新增、查询、结算的流程。因为无痕模式能清掉本地缓存和token还原一个新用户首次访问的真实状态很多部署后的隐藏问题都要靠这种方法才能暴露出来。8. 万字论文怎么组织从需求分析到测试验收配套论文文档是这个项目交付物里另一个重量级部分。一万字的论文对应一个完整的信息系统结构上基本是固定的但每部分的篇幅分配和写法有不少讲究。8.1 论文章节与字数分配一篇标准的毕业设计论文结构是这样的摘要300到500字第一章绪论写项目背景、研究目的和内容第二章相关技术介绍第三章系统需求分析第四章系统设计包括总体架构和数据库设计第五章系统实现配核心功能截图第六章系统测试最后是总结和参考文献。篇幅分配我的建议是相关技术介绍写1500到2000字这部分最好写但也最容易写成一堆官方文档的搬运。别大段抄Vue官方文档每项技术用“是什么、为什么选它、在本系统中承担什么角色”三段式来写既专业又不容易被判重复。系统设计和数据库设计是最容易出彩的部分功能模块图、用例图、E-R图、表结构说明都放这里这部分至少2500字。系统实现配合界面截图每个截图配一到两段文字说明核心功能的前后端实现逻辑大约2000字。再加需求分析、测试、总结全文字数轻松过万。8.2 系统测试用例写作系统测试部分一定要用表格列测试用例格式是测试模块、测试步骤、预期结果、实际结果。至少写15条以上覆盖所有核心功能。我列几条模板测试模块测试步骤预期结果实际结果登录模块输入正确账号密码点击登录跳转到系统首页通过宠物档案新增宠物并填写完整信息列表出现新记录通过商品搜索按名称模糊搜索商品返回匹配结果通过寄养结算设置入店和离店日期选择会员折扣计算出的总费用正确通过订单退货对已售商品执行退货库存回补、生成退货记录通过测试用例要和系统里的数据对得上答辩时老师会直接点开页面验证所以测试结论里写的一切都要能现场复现。写“通过”之前自己先在系统里把这一条用例走一遍。8.3 答辩常见问题预设答辩时老师最爱问的几个问题提前准备一下答案第一个是“这个系统怎么保证数据一致性”。可以从三个角度回答数据库事务保证订单和库存的原子性逻辑外键控制关联数据的正确性状态字段控制业务流转。第二个是“用户量变大了哪个环节是性能瓶颈”。可以答MySQL索引优化、分页查询减少数据载入、Nginx静态缓存、后端懒加载等。第三个是“为什么选择前后端分离”。可以从开发效率、部署灵活、职责清晰三个角度展开再结合技术选型部分讲。提前把这些问题想清楚比答辩现场临时翻代码强得多。写论文本质上也是在逼自己把这些问题的答案想清楚所以论文别拖到最后一周赶边写码边写论文思路是连贯的。9. 我给这类项目定的一份“完成清单”最后分享我每次带完这类完整交付项目后固定会复查的几个点。你可以把它当作一个项目交付检查表来用代码层面所有接口都统一返回格式所有axios请求都走封装所有错误都有统一提示。数据层面初始化数据能完整支撑演示核心表都有测试数据SQL脚本命名清晰。文档层面README包含环境要求、启动步骤、数据库初始化说明部署文档附Nginx配置示例。演示层面准备一条完整演示路径登录→新增宠物→下单→寄养→查看统计报表全程不报英文异常。我在带项目的过程中感受最深的一点是这种课程设计级别的管理系统技术难度其实并不高真正拉开差距的是工程规范意识。同一个功能有人能一气呵成地演示有人每次都在关键时候环境崩掉差别往往就在有没有提前把每一步流程跑通、有没有把依赖版本固定住、有没有把接口数据结构对齐。所以哪怕时间再紧也一定留出至少半天时间从零开始把MySQL→后端→前端这条链路完整走一遍。这类项目拿到手的时候先不要急着“开始写功能”花一个晚上把环境、数据库、前后端骨架、部署流程全部准备到位后面所有模块的开发都会快很多。我自己做这类交付项目一半以上的时间都花在这些“看不见但绕不开”的基础工作上这也是最能体现经验的地方。