做毕业设计最怕什么不是不会写代码而是题目选大了、框架选重了、做到一半发现到处是坑。客户关系管理系统CRM在Java方向的毕业设计里一直是最稳妥的选题之一因为业务模型很清晰无非是客户、联系人、跟进记录、商机、合同这一条线。但越是这样常见的题目越容易做成流水账。这篇指南围绕一个实际完成并顺利通过答辩的SSMVueMySQL小型CRM项目把从需求分析、数据库设计、后端接口到前端页面的完整流程拆开讲顺便把踩过的坑和解决办法一并写出来。只要你打算做类似题目或者基础一般又想冲一个良好成绩照着这条链路走能少走两个星期的弯路。1. 项目从0到1先想清楚再动手1.1 这类题目为什么适合毕业设计CRM系统之所以被反复选作毕业设计是因为它的业务边界非常清楚。小型企业的客户管理核心动作只有几个录入客户、分配跟进人、记录跟进过程、跟踪商机、最终签单再往后就是售后维护。这套流程不需要复杂算法也不需要海量数据但对增删改查、表关系设计、前后端联调、权限控制这些基本功的覆盖非常全面老师一眼就能看出你掌握没掌握。更重要的是CRM系统天然有“故事线”。答辩的时候你可以顺着一个小型企业销售的真实工作场景讲销售登录系统看到一个潜在客户列表点进详情看了历史跟进记录继续添加一条跟进把商机状态从“报价”推到“谈判”最后录入成交合同。整个讲述有逻辑、有数据、有页面比空谈“我做了个后台管理”要扎实很多。另外这类系统的功能模块可以灵活裁剪。如果时间紧张砍掉合同、统计只保留客户、联系人和跟进记录也能成立如果想冲优秀加上数据可视化、导出Excel、操作日志又可以作为亮点。我自己做的时候就是按这种“核心必做、加分选做”的思路来排优先级最后效果很好也没有出现临近答辩还在一锅粥的状态。1.2 技术选型不是凑热闹而是有取舍标题里的SSMVueMySQL不是随意拼起来的它代表了一套非常成熟的毕业生技术栈。SSM指的是Spring SpringMVC MyBatis是Java后端里经典的三层框架组合Vue负责前端页面与交互MySQL存数据。为什么不用更流行的SpringBoot其实SpringBoot底层仍然是SSM那套东西只是把配置简化了。对毕业设计来说用传统SSM至少有两个好处第一你能把框架整合的原理讲清楚比如DispatcherServlet、SqlSessionFactory、Mapper扫描这些概念答辩时有话讲第二很多学校的课程设计和旧项目模板还在用SSM资料多遇到问题容易搜到。选择Vue而不是JSP也挺关键。JSP时代的做法是把页面塞进后端前后端耦合严重展示逻辑全部混在一起维护很痛苦。Vue负责前端渲染后端只提供JSON接口两边通过HTTP通信这种“前后端分离”模式是目前企业开发的主流写在论文里也更有时代感。Vue你不需要学得多深会组件、路由、Axios调用、表单绑定这四样已经足够撑起一个CRM系统。MySQL的选择更简单免费、轻量、装机率高毕设场景根本用不到Oracle这种重型数据库。需要注意版本选择后面我会单独说有坑。总之这个组合的定位是“经典、够用、好解释”它不是最强的但它是你在有限时间成本内最稳的。2. 环境搭建与项目骨架初始化2.1 本地开发环境版本选择我强烈建议在动手写代码前先把所有环境版本统一好不要用最新的也不要用太老的。拿我当时的配置举例JDK 1.8、Maven 3.6.3、Tomcat 8.5、MySQL 5.7后端框架用Spring 5.0.x、SpringMVC 5.0.x、MyBatis 3.5.x。前端用Vue 2.6 Vue CLI 4 Element UI 2.15。这个组合虽然不算新但兼容性经过大量项目验证网上的报错解决方案几乎一搜一个准。这里单独提醒一下MySQL版本。MySQL 8.0现在已经很常用但它默认的认证插件是caching_sha2_password老版本的JDBC驱动连接时会报认证失败。如果你执意用MySQL 8.0记得把驱动换成mysql-connector-java 8.0以上并在连接串里加上allowPublicKeyRetrievaltrue。对毕设项目来说用MySQL 5.7依然是个非常务实的选择稳定坑少。前端环境方面Node版本也值得注意。Vue CLI 4对Node版本的兼容区间是12到16如果你电脑上装了Node 18以上建议用nvm切到Node 14或者16再创建项目。我见过很多同学卡在npm run serve起不来其实就是Node版本太新导致的。装好Node之后顺手把npm镜像切到国内源后面安装依赖会快很多这个属于国内开发者的基操。2.2 后端SSM项目骨架创建后端项目我推荐直接用IDEA创建Maven项目然后手动引入依赖不需要去用Spring Initializr。因为SSM毕竟是三个框架手动整合只有自己把每个配置文件写一遍才能理解它们各自角色是什么。项目结构建议按下面这样建crm-backend ├── src/main/java/com/example/crm │ ├── controller │ ├── service │ ├── mapper │ ├── entity │ ├── common │ └── interceptor ├── src/main/resources │ ├── mybatis-config.xml │ ├── spring-mvc.xml │ ├── spring-mybatis.xml │ ├── jdbc.properties │ └── mapper └── src/main/webapp/WEB-INF/web.xmlMaven的pom.xml里核心依赖包括spring-context、spring-webmvc、mybatis、mybatis-spring、mysql-connector-java、druid连接池、jackson-databind、pagehelper分页插件、servlet-api和junit。这些依赖版本要互相匹配我的做法是去Maven中央仓库查mybatis-spring的对应版本说明然后让Spring版本和它对齐避免运行时报NoSuchMethodError这种玄学错误。配置文件里最容易出错的是web.xml。你要同时配置Spring容器监听器和SpringMVC的前端控制器DispatcherServlet并且要注意spring-mybatis.xml由ContextLoaderListener加载spring-mvc.xml由DispatcherServlet加载。如果两个配置文件的扫描范围重叠会导致Bean被创建两次后面注入依赖时各种怪异问题。我在项目里用了一个比较简单的方案spring-mybatis.xml只扫描service和mapper相关spring-mvc.xml只扫描controller把边界划清。2.3 前端Vue项目初始化前端项目建议用命令行创建别手动抄文件vue create crm-frontend创建时选择Manually select features勾选Router和VuexCSS预处理器可以选择Less或者干脆不选然后用默认的ESLint配置。Vue版本选2.x因为Element UI不支持Vue3如果你想用Vue3就得换Element Plus说实话对毕设来说差异不大但Vue2资料还是最多。项目创建成功后再安装几个必要依赖npm install element-ui npm install axios npm install echarts npm install nprogress目录结构建议自行调整为src/views ├── Login.vue ├── Layout.vue ├── dashboard/Dashboard.vue ├── customer/CustomerList.vue ├── customer/CustomerDetail.vue ├── contact/ContactList.vue ├── follow/FollowList.vue ├── opportunity/OpportunityList.vue └── contract/ContractList.vue路由配置的时候可以把登录页设置成独立路由其余页面通过Layout组件嵌套使用懒加载的方式引入组件。这样启动时不会一次性加载所有JS文件答辩演示时页面切换也更流畅。前端环境这块最常见的坑是依赖安装失败别慌优先检查npm镜像再把node_modules删掉重装大部分问题都能解决。3. 数据库设计与初始化3.1 六张核心表如何设计数据库是CRM系统的地基表关系设计得合理后面写代码会非常顺。我设计的库名就叫crm一共六张表用户表、客户表、联系人表、跟进记录表、商机表、合同表。客户表是核心联系人和跟进记录都挂在客户下面商机挂客户合同挂商机整体是一条完整的销售链条。客户表customer的字段建议这样规划id、customer_name、industry所属行业、level客户等级0普通1重要2 VIP、source客户来源、status客户状态0潜在1成交2流失、phone、email、address、owner_id负责销售的用户ID、create_time、update_time。这里要注意不要在表里直接存用户名而是存owner_id以后要查“张三名下的客户”只需要一次JOIN或子查询数据更规范。跟进记录表follow_record要记录跟客户有关的每次沟通id、customer_id、content、next_time下次跟进时间、create_time。这张表一定不要存冗余的客户名称需要展示时再关联查询否则更新客户名称时会牵连一堆脏数据。商机表opportunity需要重点设计状态字段stage用0到5分别表示初识、需求确认、方案报价、谈判、成交、流失可以用一个整数维护前端再映射成中文标签这样比直接存字符串更省空间、也好做统计。3.2 建表SQL与初始化数据要点建表的时候字符集必须指定utf8mb4不要只写utf8。原因很简单utf8mb4才能存emoji和生僻字客户备注里万一有特殊字符用utf8直接报错或问号。排序规则用utf8mb4_general_ci就够了。所有表的主键我统一用INT自增业务表都加create_time和update_time方便排序和排查问题。客户表的核心建表语句大概长这样CREATE TABLE customer ( id INT NOT NULL AUTO_INCREMENT COMMENT 客户ID, customer_name VARCHAR(100) NOT NULL COMMENT 客户名称, industry VARCHAR(50) DEFAULT NULL COMMENT 所属行业, level TINYINT DEFAULT 0 COMMENT 客户等级 0普通 1重要 2VIP, source VARCHAR(50) DEFAULT NULL COMMENT 客户来源, status TINYINT DEFAULT 0 COMMENT 客户状态 0潜在 1成交 2流失, phone VARCHAR(30) DEFAULT NULL COMMENT 联系电话, email VARCHAR(100) DEFAULT NULL COMMENT 邮箱, address VARCHAR(200) DEFAULT NULL COMMENT 地址, owner_id INT DEFAULT NULL COMMENT 负责销售, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), KEY idx_owner_id (owner_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT客户表;这里有几个细节值得说。status字段设置DEFAULT 0对应mysql设置默认值为0的使用场景create_time用CURRENT_TIMESTAMP自动填充插入时不用手动赋值update_time配合ON UPDATE CURRENT_TIMESTAMP修改记录时自动更新非常省事。另外在owner_id和status上建索引是为了后面统计“每个销售有多少潜在客户”这类查询时不至于全表扫描。初始化数据建议先插一个管理员账号密码不要用明文。我记得当时用MD5(123456)放进数据库虽然强度不高但作为毕设展示已经够用。然后顺便插几条带不同行业、不同状态的客户样例这样前端页面一打开就有数据演示效果会比空表好很多。样例数据还能让你提前发现字段设计问题比如地址长度不够、行业名乱码这些越早发现越省事。4. 后端接口开发4.1 三层架构落地Controller/Service/Mapper后端开发的核心就是按Controller、Service、Mapper三层往里面填代码。Mapper层只管和数据库交互Service层负责业务规则Controller层只做参数接收和结果返回。规矩定死之后团队协作或者自己写代码都不容易乱。以“分页查询客户列表”这个功能为例。Controller里接收pageNum、pageSize、customerName等参数调用Service。Service层先校验页码不能小于1再调用Mapper接口。Mapper接口定义如下ListCustomer selectCustomerList(Param(customerName) String customerName, Param(ownerId) Integer ownerId);对应的Mapper XML写一条动态SQLselect idselectCustomerList resultTypecom.example.crm.entity.Customer SELECT id, customer_name, industry, level, source, status, phone, email, owner_id, create_time, update_time FROM customer where if testcustomerName ! null and customerName ! AND customer_name LIKE CONCAT(%, #{customerName}, %) /if if testownerId ! null AND owner_id #{ownerId} /if /where ORDER BY create_time DESC /selectwhere标签很实用它会自动去掉第一个多余的AND不用你手动拼接条件。LIKE的模糊查询注意用CONCAT拼接不要直接在SQL里写成%${customerName}%那样会有SQL注入风险。排序我统一用了ORDER BY create_time DESC让最新客户排在前面这也是mysql排序里最常见的要求。分页我用的是PageHelper插件。Service层在查询前调用PageHelper.startPage(pageNum, pageSize)然后直接执行List查询PageHelper会通过拦截器自动改写SQL帮你加上LIMIT并把总条数放到PageInfo里。返回给前端时统一用PageInfo对象包含records、total、current、pages这几个字段前端表格和分页组件直接绑定逻辑很干净。4.2 登录、拦截器与统一响应后端不能裸奔所有业务接口都要做登录校验。我的方案是基于Session的登录状态判断用户输入账号密码Service层把密码做MD5处理后和数据库比对比对成功就把user对象放入session。然后写一个HandlerInterceptor在preHandle里检查session里有没有user没有就返回401状态码前端收到后跳回登录页。拦截器需要在spring-mvc.xml里注册mvc:interceptors mvc:interceptor mvc:mapping path/api/**/ mvc:exclude-mapping path/api/user/login/ mvc:exclude-mapping path/api/user/register/ bean classcom.example.crm.interceptor.LoginInterceptor/ /mvc:interceptor /mvc:interceptors注意上面的配置只拦截/api/**登录接口放行。这里还有个坑如果前端使用了跨域请求浏览器会先发一个OPTIONS预检请求这个请求没有session容易被拦截器拦掉。解决办法很简单在拦截器里判断request.getMethod().equals(OPTIONS)直接放行。统一响应是我强烈推荐的规范。后端所有接口都返回同一个JSON结构{ code: 200, message: 操作成功, data: {} }前端Axios在响应拦截器里统一判断code只有200才走成功回调其他弹错误消息。这样做的好处是前端处理逻辑完全统一后端抛异常时也能在全局异常处理器里转换成友好提示而不是直接把堆栈信息返回给页面。Controller代码也会非常简洁只需要写业务调用不需要每个方法都去拼HashMap返回。5. 前端页面实现5.1 路由、请求封装与登录页前端这边我建议先把基础设施搭好再去做具体页面。路由上面的章节已经提过这里重点说Axios封装。直接在每个组件里import axios再用代码会重复且难以维护。正确做法是建一个src/utils/request.js实例化axios并设置baseURL: /api然后加请求拦截器和响应拦截器。请求拦截器主要做两件事一是把session中已有的登录标识放到请求头里方便后端识别二是统一开启loading进度条。响应拦截器则是判断后端返回的code如果code不是200就用Element UI的Message组件弹出错误提示同时清空loading状态。如果遇到401直接router.push(/login)。这样一来业务组件里写请求代码会非常短可读性很高。登录页本身没什么技术含量用Element UI的el-form绑定表单校验用户名和密码非空提交时调用login接口。但有一个体验细节很加分登录成功后不要只跳转到首页而是根据用户角色跳转到不同默认页这个用后端返回的user对象里的role字段判断即可。如果答辩老师问到权限控制你还能顺势讲出动态路由的思路前端只放公共路由业务路由根据角色过滤后动态添加也就是vue路由里经常提到的动态路由。5.2 客户管理列表的CRUD完整实现客户列表页是整个系统里功能最全、也最能体现代码水平的页面。页面结构是三块顶部搜索栏、中间表格、底部弹窗表单。搜索栏里有客户名称输入框、所属行业下拉框、状态下拉框、查询按钮和重置按钮表格展示客户基本信息操作列里有编辑、详情、删除按钮。前端请求数据的关键代码其实很短loadData() { const params { pageNum: this.pageNum, pageSize: this.pageSize, customerName: this.keyword, status: this.status } getCustomerList(params).then(res { this.list res.data.records this.total res.data.total }) }这里我踩过一个坑pageNum和pageSize是数字类型但如果URL地址栏传参时浏览器会自动转成字符串后端PageHelper也能正常解析不必太担心。真正要留意的是日期字段回显后端返回的create_time是2024-06-01 15:30:00这种字符串还是时间戳取决于Jackson配置。我在后端全局配置了日期格式化前端就不用再写一堆format函数了。新增和编辑可以共用一个el-dialog。点击新增时表单清空点击编辑时先根据当前行数据回填提交时调用同一个save接口。删除操作不要用原生confirm而是用ElMessageBox.confirm确认后再调接口删除结束后刷新当前页。这里要记住一个前端体验小技巧如果当前页只剩一条数据删除成功后页码要减1否则会请求到空页。5.3 数据统计可视化如果想让项目在答辩时更有亮点强烈建议加一个数据可视化看板。我用ECharts做了三个图客户行业分布饼图、商机阶段漏斗图、近30天跟进记录趋势图。这三个图不需要多复杂的数据但展示效果非常直观而且实现成本不高。后端为统计单独写一个接口用聚合查询直接出结果。比如行业分布SELECT industry AS name, COUNT(*) AS value FROM customer WHERE is_deleted 0 GROUP BY industry ORDER BY value DESC这个SQL用到了GROUP BY聚合统计返回的数据结构正好是ECharts饼图需要的[{name: 制造业, value: 12}, {name: IT, value: 8}]形式。前端拿到以后几行代码就能初始化图表。记得图表容器要设置明确高度否则ECharts初始化时高度为0图表显示不出来这是前端新手最容易卡住的地方。还有一点统计页不要一加载就同时发多个请求建议用Promise.all把行业、阶段、趋势三个请求并行发出全部成功后再渲染图表既快又优雅。如果你还想加个筛选条件比如只看当前负责人的数据后端接口多接收一个ownerId参数就行前端加个下拉框联动刷新这又是一个可以写进论文里的“业务细节”。6. 联调、部署与避坑实录6.1 前后端联调的关键配置前后端分离开发时本地联调最常用的是Vue CLI的devServer代理。我在vue.config.js里这样配置module.exports { devServer: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } }这个配置的含义是前端启动在3000端口所有以/api开头的请求都转发到后端8080端口同时把路径里的/api去掉。后端SpringMVC里的Controller实际路径就是/customer/list所以前端请求写/api/customer/list代理转发后变为http://localhost:8080/customer/list就能命中后端接口。这块需要理解否则后端控制台一直报404但你找不出原因。如果不用代理也可以在SpringMVC里配置全局CORS允许前端跨域访问。但这个方法比较麻烦因为跨域请求会带上Origin头后端要处理OPTIONS预检、还要配置允许的请求头、允许携带凭证稍不注意就出问题。我建议开发阶段用代理部署阶段让前端静态文件和后端跑在同一个域名下基本能绕开跨域这个大坑。6.2 部署到服务器或者答辩环境答辩时候最怕现场环境不一致代码到另一台电脑上跑不起来。我强烈建议你至少提前一周做一次“从零部署”演练关闭当前开发环境按照答辩电脑的配置重新搭一遍。如果答辩现场允许自带电脑那就提前把整套软件环境装好并且准备一个“环境自检清单”包括JDK版本、MySQL服务是否启动、Tomcat是否正常、Node版本、npm依赖是否完整。传统SSM项目的部署路径大致是先mvn clean package打成war包然后放到Tomcat的webapps目录下启动Tomcat后war包自动解压。前端执行npm run build生成dist目录把dist里的文件复制到Tomcat对应webapp的根目录或者用Nginx单独托管前端静态文件后端接口通过反向代理转发到Tomcat。我实际答辩时用的是Tomcat统一托管前端dist直接放到了war包解压后的目录里这样所有请求都是同域几乎不用处理跨域。需要注意的是前端打包时的资源路径。如果Vue项目部署到Tomcat的非根路径要修改vue.config.js里的publicPath否则JS和CSS文件会加载不出来。这个错误非常典型HTML能打开但页面空白控制台报一堆资源404。提前打包一次就能发现。6.3 高频报错与排查速查表这里把我在整个开发过程中遇到的高频问题整理成一张表每条都是真实踩过的坑不是文档里编出来的。报错现象常见原因解决办法ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sockMySQL服务未启动或客户端默认走socket连接检查MySQL服务是否启动改用mysql -h 127.0.0.1 -P 3306 -u root -p连接JDBC连接报Public Key Retrieval is not allowedMySQL 8.0的认证插件问题在连接串加allowPublicKeyRetrievaltrueuseSSLfalse或选用5.7版本数据库中文乱码库表字符集不是utf8mb4或连接串缺characterEncoding建库时指定utf8mb4连接串加characterEncodingutf8后端返回值没有createTime字段MyBatis没开启驼峰映射或实体类字段名不一致mybatis-config.xml里设置mapUnderscoreToCoreCasetrue页面请求404代理没生效devServer proxy配错或路径重写不正确检查vue.config.js代理配置和后端Controller实际路径对比使用Maven打包报依赖缺失本地仓库下载不完整删除~/.m2/repository中对应目录重新mvn clean installTomcat启动时报ClassNotFound依赖scope错误或war包没打全检查servlet-api等依赖是否为provided执行clean后重新package这里单独说一下MySQL连接串的最佳实践。完整写法是jdbc.urljdbc:mysql://localhost:3306/crm?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiuseSSLfalse是因为本地开发不需要SSL加密加了反而可能出现证书警告serverTimezone是MySQL 8.0和Java时区不一致时的解决办法。有人会在MySQL的配置文件里手动改默认端口或者socket路径但我建议保持默认减少环境差异。如果你的开发机是Linux虚拟机安装MySQL时还会遇到初始化密码、权限配置一类的问题建议全程用sudo systemctl status mysql或service mysql status检查服务状态装完以后用mysql_secure_installation做一次安全初始化顺便把root密码改成你方便记忆的。毕设阶段不需要太复杂的数据库运维服务能起、能连、能建库就行。我个人在做这个项目的过程中最深刻的体会是真正花时间的不是CRUD代码本身而是各种“环境级”问题——JDK版本不对、Maven依赖冲突、MySQL连不上、前端资源加载失败。但只要按顺序把环境确认一遍、把配置统一一遍、把联调代理配好后面写业务代码反而是水到渠成的事。这个小型CRM做下来你对SSM框架的整合流程、Vue的前后端分离模式、MySQL的表设计与查询都会有一个完整的认知。如果时间有余你还可以继续加功能比如用Spring Task写一个定时任务自动给长时间未跟进的客户打上“需要关注”标签或者引入Apache POI做客户数据导出Excel。这些扩展不用改动核心架构但会让项目成品丰满很多。
企业数字化 ERP 产品动态
相关推荐
图书馆管理系统毕业设计怎么做?从Spring Boot到事务并发一次讲透 每年三四月份,我的私信箱里就会被同一个问题刷屏:毕设不知道选什么题,图书馆管理系统是不是太老了?这个题目确实不新——但凡用Java做过课设的人,几乎都绕不开图书管理、学生管理、酒店管理这"老三样"。但我… · 2026/9/26 20:19:05
Agent数据治理实战:EU AI Act与GDPR合规架构设计 1. 当Agent开始处理用户数据,合规就不再是法务的事做Agent开发的同行大概都有这种体会:前几个月还在纠结prompt怎么写、工具怎么调、记忆怎么存,转眼间项目要上线了,法务突然甩过来一份问卷,问你的Agent有没有做数据分… · 2026/9/26 20:19:05
CLI工具链整合实战:MCP协议与多模型API统一管理 1. 从"treg"这个标题说起:一个被低估的CLI工具链整合思路第一次看到"treg"这个标题的时候,我承认我愣了一下。没有正文,没有关键词,没有摘要,只有一个孤零零的四个字母。但结合后面那串热搜词——… · 2026/9/26 20:19:05
Gemini CLI 开发实战指南:用 TaoToken 统一 Key 打通 AI 应用命令行工作流 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 20:55:43
WSL 2 + Ubuntu 24.04 开发环境搭建全攻略 在 Windows 上折腾 Linux 开发环境,过去绕不开双系统或者虚拟机。双系统重启切换太麻烦,虚拟机又始终隔着一层,性能损耗和内存占用都肉眼可见。这两年我基本固定在一套组合里:Windows 11 WSL 2 Ubuntu 24.04,日常的 … · 2026/9/26 20:55:37
开放式代码评审实践:从流程设计到团队知识管理 1. 我为什么会重新审视 Code Review做软件开发这些年,我最怕听到的一句话就是“代码过了,合并吧”。乍一听没毛病,但仔细一问,所谓“过了”往往是:提交者自己在机器上跑通了、CI 绿了、或者同事扫了一眼没发现问题。真… · 2026/9/26 20:55:37
基于YOLOv8的地下管廊积水渗漏检测:毕设项目拆解与复现要点 简介:面向计算机相关专业学生与毕业设计人员,这套基于YOLOv8的智慧城市地下管廊积水渗漏检测系统提供了完整可运行的目标检测方案。包内共8个文件,以Python脚本、PyTorch权重和说明文档为主,分别承担可视化界面、模型训练、视频检… · 2026/9/26 20:55:24
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46