
1. 为什么我坚持用C# ASP.NET来做这个旅游管理系统先交代一下背景。这个项目是我给学生做毕业设计时接到的一个需求开发一套西藏旅游管理系统。选型的时候其实纠结过一阵子PHP、Java、Python都能做这类Web系统但最终还是敲定了C# ASP.NET这个组合。这里面的考量值得展开说说因为技术选型直接决定了后期开发的效率也决定了你遇到问题能不能快速找到答案。先说C#本身。C#是一门语法非常严谨的强类型语言对初学者来说“类型安全”意味着很多错误在编译阶段就会被拦下来而不是运行到一半页面突然500。做旅游管理系统这种典型的信息管理系统涉及大量的增删改查、表单提交、数据绑定C#的强类型特性和完善的IDE支持Visual Studio那套调试体验能帮你省掉大量低级错误排查时间。还有一个隐性优势C#和SQL Server是同门产品写SQL、做连接、做数据操作的时候不会遇到奇怪的驱动兼容性问题。再说ASP.NET。注意这里要区分一下传统的ASP.NET Web Forms和后来主流的ASP.NET Core MVC是两个时代的东西。这个项目用的是ASP.NET Core MVC如果是老版本的.NET Framework也有对应的ASP.NET MVC 5思路基本一致。为什么选MVC而不是Web Forms因为MVC把“页面展示”和“业务逻辑”分得很干净Controller接收请求、处理数据、返回视图Model承载数据View只负责呈现。这种分层对维护太重要了——旅游系统的景点介绍页、线路报价页、订单管理页页面数量一多Web Forms那种事件驱动模型会越改越乱而MVC的清晰分层让我能在后面的迭代中快速定位问题。还有一点很实际这类系统的“标配”功能——用户注册登录、景点列表分页、后台数据管理、文件上传景点图片——在ASP.NET生态里有大量现成的组件和教程可以参考。C#社区不像Java那么重也不像PHP那么散很多东西都很顺手。比如分页有X.PagedList导出Excel有NPOI做验证有内置的DataAnnotations几乎不用自己造轮子。所以结论很明确如果你需要的是一个开发速度快、结构清晰、资料好找、交付之后还能让客户或者导师看得懂的系统C# ASP.NET Core MVC是非常稳的选择。而且西藏旅游管理系统这个场景业务不算特别复杂正好是这个技术栈的舒适区。提示如果你手头是旧版本的VS或者老师指定要用“.NET Framework ASP.NET MVC 5”下文提到的所有设计思路依然适用把依赖注入和EF Core换成就地写法就行功能上不冲突。2. 系统功能拆解前台“游西藏”和后台“管西藏”两大块这是整个项目最核心的架构设计阶段。拿到“西藏旅游管理系统”这个需求时第一件事不是写代码而是把业务捋清楚。我习惯把这类系统拆成“前台展示”和“后台管理”两个子系统职责分明一套代码一个解决方案但逻辑上完全解耦。2.1 前台门户用户看到的是什么前台的定位是面向普通游客的“官网式”门户整体氛围要体现西藏的自然和人文特色。具体功能拆分如下首页轮播图布达拉宫、纳木错、珠峰大本营等景点图、热门线路推荐、最新旅游资讯公告。景点模块按地区分类拉萨、林芝、日喀则、阿里等列表展示景点名称、所在地区、简介、图片详情页展示开放时间、门票参考价、交通方式、注意事项。线路模块展示旅游线路如“拉萨—林芝—雅鲁藏布大峡谷七日游”每条线路包含行程天数、价格、出发城市、行程亮点、详细行程安排。酒店模块按城市查询酒店展示档次、价格、设施服务和联系方式支持按星级筛选。旅游攻略后台编辑发布的图文内容包括高原反应应对、必备物品清单、边防证办理流程等实用信息。注册登录与个人中心注册登录后可以收藏景点、收藏线路、提交预订订单并查看订单状态。在线预订用户在线路详情页选择出发日期、出行人数填写联系人信息提交预订申请。流程上要特别留一个心眼西藏旅游有特殊性部分线路涉及边境地区比如珠峰大本营、阿里地区需要边防证。所以在线预订的表单设计我刻意加了一个“是否需要协助办理边防证”的选项和“出行月份”字段这些细节是西藏旅游区别于普通旅游系统的关键后面会专门讲。2.2 后台管理管理员怎么维护内容后台的角色是管理员和编辑人员。考虑到毕业设计答辩和实际维护两方面的需求后台权限分成了两级超级管理员管理用户账号、权限分配、数据统计。内容管理员维护景点、线路、酒店、攻略、公告等业务内容处理订单状态待确认、已确认、已取消、已完成。后台功能模块列表如下模块核心功能景点管理对景点信息做增删改查图片上传、地区分类设置线路管理管理线路基础信息、行程安排、报价和上下架状态酒店管理按城市维护酒店信息、设施标签、价格区间订单管理查看用户预订记录回复确认更新订单状态攻略管理发布和编辑旅游攻略、资讯公告类似于轻量级CMS用户管理查看注册用户列表启用/禁用账号封禁恶意用户留言/评价管理审核用户对景点的评价、留言防止不当内容公开展示这个后台其实就是典型的“CRUD集合体”单看每个模块都不难但组合在一起你必须提前想好通用的列表页、新增页、编辑页怎么复用布局减少大量重复代码。我的做法是写了一个BaseController基类把分页参数接收、操作成功/失败的返回值统一封装后台各个模块的Controller都继承它代码量直接砍掉三分之一。2.3 角色权限的落地思路权限这块用最简单的Cookie-based认证就够了不用上IdentityServer那么重的框架。ASP.NET Core自带的Cookie认证中间件配合自定义的Role字段——用户登录成功后把用户ID、用户名、角色写进ClaimsPrincipal然后在控制器或Action上加[Authorize(Roles Admin)]特性。这样游客访问后台地址会被自动重定向到登录页普通用户即使手动输入后台URL也会被拒之门外。具体实现很简单注册Cookie认证服务时指定登录页地址然后登录接口里用SignInAsync签发凭证。数据表里users表加一个role字段区分“admin”和“user”就行。这种方法的好处是完全可控、没有黑魔法答辩的时候三言两语能讲清楚。3. 数据库设计围绕旅游业务的那六张核心表数据库是这类管理系统的命脉表结构设计得不好后面写代码全是泪。我当时画E-R图加建表花了两天时间反复调整。这里分享最终定稿的核心表结构已经去掉了一些冗余设计保留了最实用的部分。3.1 核心表概览总共设计了9张表其中6张是业务核心另外3张是辅助表表名说明Users用户表存注册用户和管理员账号ScenicSpots景点表存西藏各景点信息TravelLines线路表存旅游线路产品Hotels酒店表存住宿资源Orders订单表存用户预订记录Favorites收藏表存用户收藏的景点/线路Guides攻略表存旅游攻略文章Comments评论表存用户对景点/线路的评价Admins管理员表也可以合并到Users里但我拆开了便于权限隔离从独立开发的角度拆9张表不算多。实际开发中很多人图省事把管理员和普通用户放一张表确实少一张表的工作量但后期如果要做操作日志、权限颗粒度控制就会很别扭。我宁可前期多花一个小时拆好也不希望后面返工。3.2 关键表字段设计挑几个典型的表说设计思路。Users用户表用户表存的是账号信息和基本资料Id、UserName、Password这里存的是哈希值不是明文、NickName、Phone、Email、Role角色字段值为0或1之类的角色标识、AvatarUrl头像路径、CreateTime。注册功能一定要做密码哈希存储。我用的是ASP.NET Core自带的PasswordHasherUser好处是哈希加盐自动实现不用自己写加密算法安全上有保障答辩时也能证明你考虑了安全常识。ScenicSpots景点表字段包括Id、Name、Region所属地区拉萨/林芝/日喀则/阿里等、Type景点类型自然风光/寺庙古迹/高原湖泊等、ImageUrl封面图路径、Price参考门票价、OpenTime开放时间、Address、Description长文本景点介绍、ViewCount点击量、CreateTime。注意这里景点图片只存路径不存图片二进制。很多人初学喜欢把图片转成字节数组存数据库这会导致数据库体积膨胀且读写变慢正确做法是文件存在服务器目录里数据库存相对路径。TravelLines线路表字段包括Id、LineName、Title比如“拉萨林芝雅鲁藏布大峡谷7日游”、Days行程天数、Price、FromCity出发城市、TravelTime最佳出行月份这里用文本比如“5月-10月”、CoverImg、Details详细行程安排长文本、Status上下架状态1上架0下架、CreateTime。线路表的Details字段会存HTML片段因为行程安排需要分段展示后台用富文本框录入展示时原样渲染。这个很常规但注意要做XSS过滤富文本是恶意脚本的重灾区。Orders订单表字段包括Id、OrderNo订单编号、UserId下单用户、LineId预订的线路、HotelId可选关联酒店、TravelDate出发日期、PeopleCount出行人数、ContactName联系人姓名、ContactPhone联系电话、NeedFrontierPermit是否需要边防证协助0/1、Remark备注、Status订单状态枚举0待确认、1已确认、2已取消、3已完成、CreateTime。这张表有两个地方是“经验之谈”一是OrderNo不要连数据库自增Id直接用导出的订单列表需要一眼看出业务含义我用的格式是日期随机数字比如20250601103012456二是Status用int枚举而不是直接存中文页面显示层再做映射这样对后续统计非常友好。3.3 表关系怎么定关系上我保持了克制Users和Orders是1对多Orders和TravelLines是多对1多个用户可以订同一个线路。Users和Favorites是1对多Favorites和ScenicSpots、TravelLines通过Type字段区分收藏对象类型。不故意加复杂的多对多关系因为这类系统没有“一个订单包含多个线路产品”的真实业务场景没必要为了展示技术强行关联。简洁的设计更容易维护也更容易跟别人讲明白。4. 核心功能实现从景点列表到订单提交的完整链路功能实现部分我挑三个最有代表性的环节展开景点列表分页前台高频展示、订单提交流程核心业务闭环、后台图片上传最容易踩坑的地方。这三个搞定了其他的CRUD都是举一反三。4.1 景点列表页分页地区筛选搜索景点数量一旦超过20个不分页的页面就没法看。我用的是X.PagedList.Mvc.Core这个库配合LINQ的Skip/Take实现。Controller里的关键代码如下public IActionResult Index(string region, string keyword, int page 1) { var query _context.ScenicSpots.Where(s s.Status 1); if (!string.IsNullOrEmpty(region)) { query query.Where(s s.Region region); } if (!string.IsNullOrEmpty(keyword)) { query query.Where(s s.Name.Contains(keyword) || s.Description.Contains(keyword)); } var spots query.OrderByDescending(s s.ViewCount) .ToPagedList(page, 9); ViewBag.Region region; ViewBag.Keyword keyword; return View(spots); }这里有个细节ToPagedList返回的是一个IPagedList对象它除了包含当前页的数据还自带TotalItemCount、PageCount、HasNextPage等属性。视图里可以做分页导航条不需要手写一堆for循环而且它能保持你在URL上携带的查询参数翻页时不会丢失筛选条件。视图端的分页渲染我是这样写的示意代码省略了样式类Html.PagedListPager(Model, page Url.Action(Index, new { region ViewBag.Region, keyword ViewBag.Keyword, page }))_index.cshtml这个页面里再用foreach循环展示景点的卡片布局。每个卡片用一张封面图加标题加简介点击跳转到详情页。这个“列表→详情”的跳转模式是整个前台的核心交互景点、线路、酒店都是同一套玩法。4.2 订单提交一次完整的事务处理订单提交是整个系统业务价值最大的地方。游客在景点或线路详情页看到“立即预订”填写人数和日期提交后后台生成一条订单记录。这里最需要注意的是事务一致性下单不仅要往Orders表插入记录还要同步处理收藏状态、更新线路的热度。任何一个环节失败都不能让用户看到“下单成功”的假象。我用的方式是EF Core的Database.BeginTransactionAsync把写操作包在事务块里[HttpPost] public async TaskIActionResult SubmitOrder(OrderCreateViewModel model) { if (!ModelState.IsValid) { return Json(new { success false, message 请完整填写订单信息 }); } await using var transaction await _context.Database.BeginTransactionAsync(); try { var order new Order { OrderNo GenerateOrderNo(), UserId currentUserId, LineId model.LineId, TravelDate model.TravelDate, PeopleCount model.PeopleCount, ContactName model.ContactName, ContactPhone model.ContactPhone, NeedFrontierPermit model.NeedFrontierPermit, Status 0, CreateTime DateTime.Now }; _context.Orders.Add(order); var line await _context.TravelLines.FindAsync(model.LineId); if (line ! null) { line.BookCount 1; // 热度加一 } await _context.SaveChangesAsync(); await transaction.CommitAsync(); return Json(new { success true, message 预订成功等待工作人员确认 }); } catch { await transaction.RollbackAsync(); return Json(new { success false, message 预订失败请重试 }); } }这里有几个针对这类管理系统的设计考量下单和支付解耦。我故意不集成在线支付因为旅游线路预订通常是线下联系旅行社确认系统层面做到“提交预订”即可。这样既符合真实业务流程又避免接入第三方支付SDK引入太多复杂度和安全风险。直接返回JSON而不是返回页面。前后端交互用fetch提交页面不用整页刷新操作体验更现代一点。这对学生项目来说是个小亮点答辩的时候演示起来也更流畅。前端做基本校验后端必须再做一次校验。DataAnnotations的[Required]等特性配合服务端的ModelState.IsValid哪怕有人绕过前端直接POST后端也能拦下来。4.3 图片上传文件路径策略与格式校验景点和线路都要传图片这个功能看着简单但要做对几个点。首先是存储位置我在wwwroot下建了一个Uploads文件夹按模块再分子目录比如/Uploads/ScenicSpots/20250601/xxx.jpg。文件名处理有个大坑用户上传的原始文件名可能是中文、包含空格甚至带了特殊字符直接存可能出问题。我的策略是取时间戳随机数生成新文件名只保留原扩展名var fileName DateTime.Now.ToString(yyyyMMddHHmmss) _ Guid.NewGuid().ToString(N).Substring(0, 6) Path.GetExtension(file.FileName);校验也必不可少限制扩展名.jpg/.jpeg/.png/.gif不用webp是因为兼容性、限制文件大小2MB以内。扩展名判断不能只信ContentType因为客户端可以伪造直接判断文件头更保险。当然对于课程设计级别判断扩展名和大小已经足够我把文件头的完整校验代码也写在里头无非是读取文件前几个字节比对。图片上传完成后把相对路径比如/Uploads/ScenicSpots/xxx.jpg存到数据库展示时在img标签的src属性里直接写这个路径。这样数据和文件是分离的备份数据库时不会带一大坨二进制部署迁移时只需把整个wwwroot文件一起拷走就行。5. 西藏旅游业务的特殊性那些通用旅游系统没有的设计既然项目叫“西藏旅游管理系统”就不能只是给普通旅游系统换个皮。西藏旅游有几个非常特殊的业务点在需求分析阶段必须要考虑进去否则系统交付了也只是个空壳。5.1 边防证信息提示与登记这个在通用旅游系统里根本不存在。西藏的边境县比如珠峰大本营所在的定日县、阿里地区的普兰县等需要边防证才能进入。作为系统设计者我做了两个动作一是所有涉及边境景点的详情页都醒目标注“需提前办理边防证”提示并在线路详情页增加“边防证说明”折叠块介绍办理流程二是在预订表单里增加“是否需要协助办理边防证”字段游客提交订单时明确勾选自己的需求。后台订单详情里会把这个字段高亮显示方便客服人员跟进。这个设计虽然只是几个字段和一个提示框但正是这些细节让系统真正“懂西藏”。5.2 高原反应与出行安全提示高原反应是进藏游客最关心的问题。景点详情页里我专门加了一个“温馨提示”区域每个景点根据海拔高度显示不同的注意事项海拔超4500米的景点纳木错、珠峰大本营提示“建议备便携氧气瓶避免剧烈运动”海拔3000米左右的林芝地区则提示“注意休息清淡饮食”。后台编辑景点时可以自定义这些提示内容。攻略模块我也预置了几篇高价值的默认内容高原反应常见症状与应对、进藏最佳月份与穿衣指南、拉萨市区必去寺庙路线。这些内容既填充了启动数据让系统上线后不显得空荡荡又给游客提供了真实的参考价值。5.3 季节性与线路定价西藏旅游的淡旺季非常分明7-9月是绝对旺季11月到次年3月很多高海拔景点会因大雪封路。所以在线路表里我增加了“最佳出行月份”字段订单列表页也加入一个“按出行月份筛选”的功能。这样后台管理员在淡季可以快速筛选出所有涉及高海拔景点的线路统一调整策略或做打包优惠而不是一条条翻。5.4 多图展示与全景图引导西藏景色本身是最大的卖点所以景点详情我用了“主图详情图集”的结构最多可以上传6张图片。虽然技术上就是多存了几行记录但游客体验完全不一样一张布达拉宫的正面照和一组包含白宫、红宫、转经廊道的组图说服力是完全不同的。注意如果系统要展示的地图导航信息比较多可以再给景点表加经度、纬度两个字段前台用静态地图API定位。这个作为可选的加分项处理就好因为涉及第三方地图服务我最初没有纳入核心功能。6. 开发过程中我踩过的几个坑这部分是我最想写的。网上教程千篇一律讲怎么搭框架、怎么写代码但真实开发中让人卡壳的往往是那些不起眼的细节。我挑四个最具代表性的坑每一个都是我花了时间解决过的。6.1 坑一EF Core与数据库映射的版本问题这个项目一开始用的是EF Core 5后来因为服务器上装了旧版运行时出现了奇怪的运行时错误。排查了半天最后发现是NuGet包版本和.NET运行时版本不一致。这个问题的本质是dotnet run编译通过不代表运行时没问题EF Core的底层依赖与运行时版本有严格对应关系。我的解决办法是统一项目目标框架为.NET 6.0EF Core降级到6.0.x版本并清空了bin和obj目录重新编译。排查过程中我还发现如果使用旧版EF Core比如3.1连接SQL ServerDateTime.Now默认值在数据库里会有毫秒误差的坑。后来统一改用数据库的GETDATE()函数作默认值彻底避开这个边界问题。建议项目从一开始就锁定目标框架和包版本不要“最新优先”。稳定能跑优先于花哨版本。6.2 坑二前端页面中文乱码发布到IIS之后景点介绍里的中文显示成“锟斤拷”乱码。第一反应是数据库编码问题检查后发现SQL Server的排序规则不是中文相关。但实际上真正的病根在于以下三个点一是数据库连接字符串里没有加Charsetutf8这样的解法SQL Server不存在这个参数二是视图文件保存编码UTF-8 with BOM导致三是IIS的静态内容压缩在处理动态页面时对响应头编码有干扰。最终的组合拳数据库表字段统一用nvarchar类型它天生存Unicode不会出现中文变问号的经典问题视图文件另存为带BOM的UTF-8并在Startup.cs的响应中间件里显式设置app.Use(async (context, next) { context.Response.ContentType text/html; charsetutf-8; await next(); });这三个动作做完乱码问题彻底消失。这个案例给到我的经验是中文乱码牵扯三个层面数据库、文件编码、HTTP响应头排查时不要只盯着一处。6.3 坑三IIS部署时访问不了静态文件本地开发环境一切正常发布到服务器之后所有CSS、JS、图片全部404。这个问题比乱码更隐蔽。检查发现是发布时漏掉了wwwroot里的静态资源——Visual Studio发布配置里默认会打包wwwroot但因为我改过项目的.csproj文件不小心把静态资源的打包项覆盖了。排查的思路是先确认项目路径下的wwwroot是否真实存在这些文件再确认发布的输出目录里有没有对应文件最后盯着IIS的“处理程序映射”看看StaticFileModule是否被禁用。我这里是发布环节的问题直接在发布配置里重新指定目标路径把整个wwwroot目录手动拷贝到服务器解决。6.4 坑四富文本内容的XSS漏洞风险后台攻略编辑用的是富文本框直接存HTML再输出到页面。乍一看没什么问题但如果不做过滤一个恶意用户或者被社工的编辑完全可以往文章里插入script标签轻则弹窗重则窃取管理员Cookie。我的处理方式内容提交时用Ganss.XSS这个库做白名单过滤只允许p、img、a、strong、em、ul、ol、li、h2、h3这些常规标签去掉script、iframe、object等危险标签。展示端再做一次编码验证。做这类系统只要涉及富文本这个环节不能省。7. 部署上线本地跑通只是开始发布到IIS才是真正的考验系统开发完不等于项目结束部署上线才是技术债集中爆发的时候。我整理了一套可复用的部署清单按照这个顺序操作能少走很多弯路。7.1 发布前要做的三件事第一件事改数据库连接字符串。开发时用appsettings.Development.json里的本地连接串发布到服务器必须换成正式环境。我建了appsettings.Production.json在启动时根据ASPNETCORE_ENVIRONMENT环境变量切换这样连接字符串不会写在代码里也不会在Git提交时泄露。第二件事关闭开发者异常页。开发模式下异常详情页会暴露完整堆栈信息生产环境一定要用app.UseExceptionHandler并记录错误日志。这是安全底线也是专业度体现。第三件事执行数据库迁移脚本。EF Core的dotnet ef migrations script命令可以生成SQL脚本把脚本放到服务器上执行一次即可。如果直接在服务器上执行Database.Migrate()也不是不行但生成SQL脚本的方式可控性更好也方便数据库管理员审核。7.2 IIS部署的完整步骤假设服务器是Windows Server已经装好了IIS和对应的ASP.NET Core Hosting Bundle。具体操作分几步在服务器上创建网站物理目录比如D:\Sites\TibetTravel把发布输出文件全部拷贝进去。在IIS里新建应用程序池选择“无托管代码”因为ASP.NET Core是自宿主进程不需要IIS托管CLR.NET CLR版本选“无托管代码”。新建网站绑定域名或IP开发阶段可以用localhost加端口号物理路径指向刚才的目录。确认web.config存在且配置正确。ASP.NET Core项目发布会自动生成web.config里面配置了aspNetCore节点的processPathdotnet和arguments.\TibetTravel.dll。为网站目录授予IIS_IUSRS用户写入权限否则图片上传和日志写入会报权限不足。还要注意一个端口问题服务器防火墙要放行网站绑定的端口云服务器还要在安全组规则里同步放行。很多人部署失败是因为只改了IIS绑定却忘了云控制台的安全组导致外部访问不了。7.3 运行时的性能与日志配置上线之后我在日志记录方面做了几个增强。核心的日志用的是内置的ILogger写到文件里。操作方面对后管的“危险操作”删除景点、删除订单、禁用用户增加了操作日志记录。这样一旦后台数据被误改能查到谁在什么时间做了什么事对毕业答辩来说也是一个讲故事的素材。缓存方面景点列表页用内存缓存把高频访问的数据缓存5分钟减少每次打开都查数据库的压力。对中小型系统来说用IIS站点的内存缓存就够了完全不需要上Redis——这也是我强调“不做过度设计”的一个例子。系统跑起来单机并发撑住几百个人同时在线毫无压力。8. 给后来者的一些使用心得项目前后做了大概一个月从需求梳理到最后部署上线中间走了不少弯路但回头看收获是实打实的。最后聊几个经验体会希望能帮到正在做同类系统的朋友。第一个体会是做这类管理系统花在“想清楚”上的时间一定要多于“敲代码”。数据库表结构想清楚了CRUD写起来就是体力活业务流程想清楚了Controller层逻辑就是翻译工作。所以我建议开发前先花至少一个晚上把表关系图画出来把每个页面的字段列出来越细越好。我见过太多人拿到需求就建项目、加模型、拖控件结果写了一半发现表缺字段、页面逻辑对不上返工成本远大于前期设计成本。第二个体会是适度借鉴但不原样照搬课程设计模板。网上确实有很多“XX旅游管理系统”的源码但直接拿一个改改文字、换换图片答辩时一问三不知反而坏事。比较好的做法是把现成项目当作API使用的参考问清楚自己项目里的关键决策为什么这么做。比如本篇反复提到的边防证处理、图片存储方案、订单状态机这些是通用的框架教程里不会教你的恰恰是你区别于“烂大街模板”的地方。第三个体会是答辩和演示的时候准备几个“有故事”的细节。比如“为什么这里要存文件路径而不是图片二进制”“为什么订单状态用int而不用中文”“为什么没做在线支付”把这类问题的合理性讲清楚比背出一堆概念要打动人得多。面试和项目验收的评委都是老手一眼能看出你是背出来的还是真做过的。这次的项目交付出去之后我又顺手给它加了两个小功能数据导入导出的Excel报表用NPOI实现和景点访问量的简单统计图表用Chart.js画柱状图。这两块在毕业设计演示时加分效果非常明显如果时间允许你也可以往这个方向扩展。内容到了这里整个系统的核心设计、代码逻辑、部署细节和避坑经验都已经讲透了按着这个思路一步步做下来你的系统一定不会差。