基于SpringBoot+Vue3+MyBatis的城市垃圾分类管理系统开发实践
做这种管理系统项目最怕的就是代码能跑、逻辑全乱。尤其垃圾分类这种业务看着简单真要把“分类标准—投放记录—积分激励—统计报表”这条链串起来表结构设计不对后面写十行SQL九行在补漏。这套基于SpringBootVue3MyBatis的城市垃圾分类管理系统属于典型的前后端分离脚手架项目适合拿来当毕业设计、课设或者作为接私活时快速搭建管理后台的底座。下面从业务边界、技术选型、表设计、后端实现、前端组织到部署联调把我实际开发中觉得最值得讲的部分拆开说。1. 这套系统到底在管什么业务边界与角色拆解先别急着写代码搞清楚“垃圾分类管理系统”和“垃圾分类识别APP”是两回事。这套系统核心管的不是“垃圾是什么”而是“垃圾怎么被正确投放、怎么被记录、怎么被激励、怎么被统计”。业务边界大致划成四个域基础数据域、投放监管域、积分激励域、统计报表域。基础数据域负责维护垃圾四分类标准——可回收物、有害垃圾、厨余垃圾、其他垃圾还有每个分类下的细类物品比如电池属于有害垃圾、剩饭属于厨余垃圾以及投放点信息、社区信息。投放监管域管的是居民的每一次投放行为从“哪个投放点、什么时间、投了什么类型、是否违规”到督导员的巡检记录。积分激励域是这套系统的灵魂居民正确投放产生积分积分可兑换日用品或抵扣物业费这就需要积分流水、兑换规则、兑换记录三张表。统计报表域则是给管理者看的小区参与率、分类准确率、每日垃圾量趋势、违规高发时段全部从投放记录表聚合出来。角色上这套系统至少要拆三种系统管理员、督导员巡检人员、居民前台端用户。管理员管基础数据和全局配置督导员通过管理端录入巡检结果、审核投放照片居民在小程序或H5端查询分类、查看个人积分。实际开发中很多人只做管理端把居民端省了结果答辩时被问“居民怎么参与”就卡壳。我的建议是至少做一个简化版居民端页面哪怕只有分类查询和模拟投放记录提交整个业务闭环才完整。技术栈放在这个业务上是合适的SpringBoot 负责提供 RESTful APIVue3 做管理后台和居民端界面MyBatis 写动态SQL处理多条件查询和联表统计MySQL 存业务数据。没有引入过重的消息队列、微服务、Redis 缓存对这个体量刚刚好——踩过的坑是有人为了简历好看硬上微服务最后项目部署都要开四五个进程完全是自找麻烦。2. 技术选型的几个关键判断为什么不是 JPA、Vue2 或 MyBatis-Plus选 SpringBoot 基本没有争议生态成熟、内嵌 Tomcat、自动配置省掉大量 XML。真正需要想清楚的是持久层框架MyBatis 和 MyBatis-Plus、Spring Data JPA 三选一这套系统选 MyBatis 是合理的因为垃圾分类管理报表多变而且统计查询的SQL没法用简单的单表CRUD表达。比如“统计每个投放点近7天各类垃圾的重量占比”这类SQL需要按投放点分组、再按分类字段交叉统计MyBatis 的 XML 里写联表查询和动态条件非常直接SQL 可控性也强方便针对慢查询做手工优化。JPA 在这个场景下反而别扭。JPA 适合实体关系稳定、以 CRUD 为主的系统而垃圾分类的报表筛选条件经常变——时间范围、投放点、分类类型、是否违规任意组合用 Specification 写动态查询远不如 MyBatis 的if标签直观。而且团队里如果还有人不太熟悉 Lambda 表达式和 Hibernate 缓存机制上手成本会更高。Vue3 相比 Vue2 最大的优势是 Composition API把“按功能组织代码”变为“按逻辑组织代码”。管理后台左侧菜单十几个页面每个页面都要请求数据、处理加载状态、维护表单校验Composition API 的usePageList、useFormDialog这类自定义组合式函数可以直接抽公共逻辑代码量直接砍半。加上 Vite 开发服务器秒级启动迭代体验比 Webpack 时代的 Vue2 舒服得多。还有一个容易被忽略的选择前端UI库。管理端推荐 Element Plus居民端如果做H5推荐 Vant。Element Plus 的表格、表单、树控件覆盖了管理后台绝大多数场景而且样式统一、文档齐全遇到问题基本搜得到答案。不要自己手写组件库浪费时间还容易出 bug。3. 数据库设计垃圾分类业务的核心表与字段建模思路数据库是这套系统最需要花时间的地方。我把核心表分成三组业务主表、流程记录表、配置辅助表。业务主表user用户表id、username、passwordBCrypt加密、real_name、phone、role_type枚举ADMIN/INSPECTOR/RESIDENT、points_balance、community_id、create_time。这里别用role这个词当字段名它是MySQL保留字写SQL时要加反引号纯属给自己找麻烦。garbage_category分类表id、name如可回收物、code如RECYCLABLE、icon_url、description、sort_order、is_deleted。这种字典类表一定要有 sort_order 排序字段前端展示顺序经常要调。waste_item物品明细表id、category_id、name、keyword、tips。这张表是给居民查“某样东西属于什么垃圾”用的比如“废旧电池”“剩饭剩菜”。keyword 字段做模糊匹配后面讲接口时再展开。drop_point投放点表id、community_id、name、address、type智能箱/普通桶、lng、lat、manager_id。community社区表id、name、address、admin_id。流程记录表drop_record投放记录表——这是全系统数据量最大、查询最复杂的表。核心字段id、user_id、drop_point_id、category_id、waste_item_id、quantity、unit千克/件、image_url、is_violation、violation_reason、inspector_id、create_time。设计这张表时有三个关键决策冗余category_id而不是关联查询。投放时物品一定属于某个分类直接存下来统计报表时省一次JOIN。is_violation用 tinyint 0/1拒绝使用字符串是/否代码判断和SQL聚合都方便。必须建联合索引(drop_point_id, create_time)和(user_id, create_time)否则数据量过万后按月查报表会全表扫描亲测 5 万条记录慢到 3 秒以上。points_record积分流水表id、user_id、change_amount、balance_after、typeINCREASE/DECREASE、biz_id关联投放记录或兑换记录、description、create_time。积分系统有个铁律每笔流水都要存balance_after对账时直接按时间倒序查出最后一笔余额即可不用SUM聚合性能好而且逻辑简单。points_exchange_item兑换商品表id、name、points_cost、stock、image_url、status、create_time。exchange_record兑换记录表id、user_id、item_id、points_cost、status、exchange_code、create_time。配置辅助表article资讯表id、title、content、cover_url、publish_time、status。用于发“垃圾分类小知识”类内容。sys_config配置表key_value 结构存每个分类对应的单次投放基础积分、积分兑换开关等。用 key_value 结构的好处是改配置不用发版坏处是类型不固定取值时要自己转型所以一般只放简单的int/boolean类型。字符集统一用utf8mb4别用utf8否则居民端提交的内容里带个 emoji 表情直接报错。排序规则选utf8mb4_general_ci即可。初始化数据时至少要准备四分类数据、15条左右常见物品明细、3个社区各配2个投放点、一个管理员账号admin/admin123密码用 BCrypt 加密、一个督导员账号、两个居民账号。没有这些基础数据前端页面全部空荡荡联调根本没法做。4. 后端落地的关键模块从统一返回到动态SQL统计后端代码分成几个层次Controller接收参数、Service业务逻辑、Mapper数据访问。包名结构建议com.xxx.garbage.controller、service、mapper、entity、dto、vo、common、config。接下来讲几个核心实现点。4.1 统一返回结构是前后端不吵架的基础所有接口返回统一格式{ code: 200, message: success, data: ... }。Code 用业务码200 成功、400 参数错误、401 未登录、403 无权限、500 系统异常。前端 Axios 响应拦截器里统一判断 code非 200 直接弹 ElMessage 错误提示不用每个页面重复写错误处理。这个结构要写成一个泛型类ResultT避免每个接口单独定义返回类型维护成本差很多。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(Integer code, String message) { ResultT result new Result(); result.setCode(code); result.setMessage(message); return result; } }4.2 登录鉴权用 JWT 拦截器不要引入 Spring Security有人一上来就整合 Spring Security OAuth2结果配置类写了三百行还经常出现放行路径没配对导致登录接口 401。这套系统角色只有三种权限模型非常简单JWT HandlerInterceptor 完全够用。登录成功生成 token过期时间设在 24 小时拦截器里校验 token 并把 userId 和 roleType 存入 ThreadLocal后续业务代码直接从UserContext.getUserId()取当前用户。# application.yml jwt: secret: your-secret-key-should-be-long-enough expire: 86400 # 秒拦截器里三个方法preHandle校验 token、放行/api/auth/login和静态资源postHandle空实现afterCompletion清理 ThreadLocal防止内存泄漏。角色校验用注解RequireRole(ADMIN)配合拦截器判断更优雅但赶时间也可以在 Controller 里手动判断看团队需求。4.3 分类查询接口MyBatis 动态 SQL 的经典场景居民端最常用的接口是“查某样东西属于什么垃圾”本质是对waste_item表的模糊搜索。前端输入“电池”后端按 name 或 keyword like 查询返回匹配物品和它所属分类。这里注意两点搜索结果条数用 LIMIT 10别一次全返回没有匹配时也要返回推荐分类这是产品细节能提升交互友好度。select idsearchWasteItem resultTypecom.xxx.garbage.vo.WasteItemVO SELECT wi.id, wi.name, wi.tips, gc.name AS category_name, gc.code AS category_code FROM waste_item wi LEFT JOIN garbage_category gc ON wi.category_id gc.id WHERE wi.is_deleted 0 if testkeyword ! null and keyword ! AND (wi.name LIKE CONCAT(%, #{keyword}, %) OR wi.keyword LIKE CONCAT(%, #{keyword}, %)) /if ORDER BY wi.id DESC LIMIT 10 /select4.4 多条件分页查询投放记录筛选投放记录是管理端列表页的核心数据筛选项包括时间范围、投放点、分类、是否违规、居民姓名。这种多条件组合必须用 MyBatiswhereif动态拼接同时用 PageHelper 做分页。业务上有几个细节查询结果需要冗余展示 user_name、drop_point_name 等关联名称直接在SQL里 LEFT JOIN不要在 Java 里循环查数据库——N1 问题就是这么产生的。select idselectDropRecordPage resultTypecom.xxx.garbage.vo.DropRecordVO SELECT dr.id, dr.user_id, u.real_name AS user_name, dr.drop_point_id, dp.name AS drop_point_name, dr.category_id, gc.name AS category_name, dr.quantity, dr.unit, dr.is_violation, dr.create_time FROM drop_record dr LEFT JOIN user u ON dr.user_id u.id LEFT JOIN drop_point dp ON dr.drop_point_id dp.id LEFT JOIN garbage_category gc ON dr.category_id gc.id where dr.is_deleted 0 if testuserId ! nullAND dr.user_id #{userId}/if if testdropPointId ! nullAND dr.drop_point_id #{dropPointId}/if if testcategoryId ! nullAND dr.category_id #{categoryId}/if if testisViolation ! nullAND dr.is_violation #{isViolation}/if if teststartTime ! nullAND dr.create_time gt; #{startTime}/if if testendTime ! nullAND dr.create_time lt; #{endTime}/if /where ORDER BY dr.create_time DESC /selectPageHelper 用法PageHelper.startPage(pageNum, pageSize); ListDropRecordVO list dropRecordMapper.selectDropRecordPage(query); PageInfoDropRecordVO pageInfo new PageInfo(list);注意startPage只能作用于下一条 SQL所以它和 Mapper 调用必须紧挨着中间不能插其他查询否则分页会串到别的查询上去。这个坑我踩过两次排查半天。4.5 月度统计报表GROUP BY 条件聚合统计每个分类的投放量占比SQL 类似SELECT gc.name AS category_name, COUNT(dr.id) AS record_count, SUM(dr.quantity) AS total_quantity FROM drop_record dr LEFT JOIN garbage_category gc ON dr.category_id gc.id WHERE dr.create_time BETWEEN #{startTime} AND #{endTime} GROUP BY dr.category_id ORDER BY total_quantity DESC前端用 ECharts 饼图展示展示类别名称和数量占比。这类统计查询建议单独建StatsMapper不要把报表SQL和业务CRUD混在一个 Mapper 里。另外报表接口考虑用Cacheable做短时间缓存比如 5 分钟避免管理端首页一刷新就压垮数据库。5. 前端 Vue3 项目结构与管理端页面组织前端我用 Vite 创建 Vue3 项目目录结构如下src/ ├── api/ # 接口请求封装 ├── assets/ ├── components/ # 公共组件 ├── composables/ # 组合式函数 ├── layout/ # 布局组件 ├── router/ # 路由配置 ├── stores/ # Pinia 状态管理 ├── views/ # 页面 │ ├── dashboard/ # 首页看板 │ ├── category/ # 分类管理 │ ├── dropRecord/ # 投放记录 │ ├── points/ # 积分管理 │ ├── user/ # 用户管理 │ ├── report/ # 统计报表 │ └── login/ # 登录 ├── utils/ # 工具函数 ├── App.vue └── main.js5.1 Axios 封装请求拦截器和响应拦截器请求拦截器统一加 token响应拦截器统一处理业务码。这里有个经验不要把response.data.code ! 200当成 HTTP 错误抛到页面里而是用 Promise.reject 走统一的错误提示这样业务代码里只需要处理成功分支不用每个页面写 try-catch。// utils/request.js import axios from axios import { ElMessage } from element-plus import router from /router const service axios.create({ baseURL: /api, timeout: 15000 }) 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) { ElMessage.error(res.message || 请求失败) if (res.code 401) { router.push(/login) } return Promise.reject(new Error(res.message)) } return res.data }, error { ElMessage.error(error.response?.data?.message || 网络异常) return Promise.reject(error) } )5.2 分类管理页面树形数据与表单弹窗分类管理如果只有四类平铺展示没问题但如果地方细分到“可回收物—纸类—旧书”就要用树形表格。Element Plus 的el-table支持row-keytree-props直接渲染树形数据后端一次性返回树结构即可。树结构在SQL里不好写建议在 Service 层递归组装从父级一直查到子级。接口返回格式{ id: 1, name: 可回收物, children: [ { id: 11, name: 纸类, children: [] }, { id: 12, name: 塑料, children: [] } ] }5.3 投放记录列表页多条件筛选与状态标签这个页面上方是筛选栏时间范围选择器、投放点下拉、分类下拉、违规状态下拉下方是表格和分页器。页面逻辑用 Composition API 组织// views/dropRecord/index.vue import { ref, reactive, onMounted } from vue import { getDropRecordPage } from /api/dropRecord const queryParams reactive({ pageNum: 1, pageSize: 10, dropPointId: null, categoryId: null, isViolation: null, startTime: null, endTime: null }) const tableData ref([]) const total ref(0) const loading ref(false) async function loadData() { loading.value true try { const { list, total: t } await getDropRecordPage(queryParams) tableData.value list total.value t } finally { loading.value false } } function handleSearch() { queryParams.pageNum 1 loadData() } onMounted(loadData)违规状态用el-tag展示绿色“正常”、红色“违规”类型的颜色可以用分类做映射——可回收物用蓝色、有害垃圾用红色、厨余垃圾用绿色、其他垃圾用灰色。这个视觉细节看起来小但实际使用时特别提升体验。5.4 统计报表页ECharts 图表整合ECharts 按需引入不要import * as echarts不然打包体积大很多。我习惯单独建一个useECharts组合式函数内部处理图表实例的创建、数据更新和组件卸载时销毁避免内存泄漏。// composables/useECharts.js import * as echarts from echarts/core import { PieChart, BarChart, LineChart } from echarts/charts import { TooltipComponent, LegendComponent, GridComponent } from echarts/components import { CanvasRenderer } from echarts/renderers echarts.use([PieChart, BarChart, LineChart, TooltipComponent, LegendComponent, GridComponent, CanvasRenderer]) export function useECharts(elRef) { let chart null function initChart() { if (elRef.value) { chart echarts.init(elRef.value) } return chart } function setOption(option) { if (!chart) initChart() chart?.setOption(option) } function resize() { chart?.resize() } function dispose() { chart?.dispose() } return { initChart, setOption, resize, dispose } }页面加载后初始化图表窗口 resize 时要监听并调用 resize 方法不然图表会变形。这个细节经常有人漏掉。6. 前后端联调与部署跨域、时间格式、打包配置前后端分离项目联调时最容易碰到三类问题跨域、时间格式、token传递。逐个说。6.1 跨域开发环境用 Vite Proxy部署用 Nginx开发环境下前端跑在 5173 端口后端跑在 8080 端口必然跨域。最省事的方案是 Vite proxy 配置前端请求/api时自动转发到后端// vite.config.js export default defineConfig({ server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })后端也配置一下跨域两种方式都做防止直接请求后端调试时被拦。后端用过滤器实现即可Configuration public class CorsConfig { Bean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedMethod(*); config.addAllowedHeader(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); } }生产环境更推荐用 Nginx 统一代理静态文件由 Nginx 直接返回/api请求反向代理到后端 jar 包。这样不仅解决跨域还能做 gzip 压缩和请求缓存。server { listen 80; server_name your-domain.com; gzip on; gzip_types text/plain application/javascript text/css application/json; location / { root /opt/garbage-system/dist; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }注意proxy_pass http://127.0.0.1:8080;结尾没有斜杠这样/api/auth/login会原样转发到后端后端 Controller 的 RequestMapping 里就直接写/api/auth/login前后端路径对齐省心。6.2 时间格式Jackson 全局配置Java 8 的 LocalDateTime 序列化默认是一长串数字前端没法直接展示。解决方式是在 application.yml 里配置格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8LocalDateTime 需要额外加JsonFormat(pattern yyyy-MM-dd HH:mm:ss)或者用自定义 Jackson 配置类统一处理。时间相关还有一个规范前端传时间范围时开始时间取当天的 00:00:00结束时间取当天的 23:59:59否则会漏掉最后一天的数据。这个在传参前处理。6.3 打包部署流程后端用 Maven 打包mvn clean package -DskipTests java -jar target/garbage-system.jar --server.port8080日志输出用nohup挂后台日志重定向到文件方便排查。前端打包npm run build产物在dist目录直接扔到 Nginx 的 root 路径下。后端接口前缀和前端 baseURL 保持一致要么都是/api要么都不带最怕前端加了后端没加联调时全部 404。7. 实际开发中我踩过的坑和调整建议最后聊点实在的。这套系统我从零开发到上线大概花了两周多时间踩过的坑集中在下面几个地方写出来帮你避免重复交学费。坑一分页插件 PageHelper 的越界使用谁用谁知道PageHelper 的startPage后如果跟着不是查询语句的 Mapper 调用分页条件会残留到下一次查询。更隐蔽的是如果查询结果没有用PageInfo接收分页总数会拿不到。建议全项目只用一种固定写法并且把分页查询封装到 BaseService 里统一走同一个入口别今天这里手动 startPage、明天那里用 PageHelper.startPage(page, size, true)。坑二垃圾图片上传没做大小和格式校验居民端提交投放记录时上传图片一开始没限制有人传了个 8MB 的图片后端处理直接内存溢出。后来统一用服务端校验格式只允许 jpg/png大小限制 2MB前端上传组件也设置limit: 1和accept。如果系统要对接人脸识别之类的服务图片压缩这步必须在服务端再做一次前端压缩不能完全信任。坑三积分一开始做成实时 SUM积分余额用 SUM(points_record.change_amount) 计算数据量上来后查询越来越慢。改成冗余字段user.points_balance每次加积分/扣积分时在事务里同时更新用户表和插入流水表查余额直接取字段十万级数据量毫无压力。这个方案有个前提积分流水必须只能通过统一 Service 方法变更不能有人直接 UPDATE user 表改积分。坑四没有预留扩展点后期加需求痛苦提测后客户提了“每个投放点可以设置不同的积分倍率”改表结构太被动。后来我在drop_point表加了points_rate字段默认 1.0投放记录积分 基础积分 × 投放点倍率。这种看似多余的设计在有政策变动时救过我一命。建议这类有规则属性的表都顺手留一个冗余扩展字段成本极低收益极高。调整建议一角色权限别写在页面里最开始的版本在前端路由的meta.roles里写死哪些角色能访问哪些页面结果是后端接口没做权限过期时间紧前端隐藏了按钮但接口还能直接调。后来后端统一加RequireRole注解前端权限只做展示控制真正的安全边界在后端。记住前端所有的控制都是体验优化不是安全机制。调整建议二响应式布局别全用 PC 端固定宽度管理端可以在 PC 上看但如果有一天需要在平板上抽查投放记录固定 1200px 宽度的布局就废了。建议用 Element Plus 的栅格布局把筛选区和表格区拆成响应式列虽然多花半天工作量但系统适用范围立刻不一样。调整建议三初始版本别上 AI 识别有人一开始就想加载 TensorFlow 部署垃圾桶图像识别模型想让系统自动识别投入的垃圾类型。理想很丰满但模型训练数据哪来、精度不达标导致错误分类怎么算积分都是说不清楚的事故。不如先保持人工选择 督导员复核的流程把系统做成可插拔架构后面模型成熟了再接入也不迟。自己的体会是这类管理系统真正的难点从来不在某个单独的技术点而在取舍的平衡。SpringBoot 和 Vue3 的技术栈让你把前后端分离的流程完整跑通MyBatis 让你把数据库的掌控权握在自己手里而垃圾分类这个业务模板恰好覆盖了 CRUD 之外的分页、统计、权限这些真实场景的需求。拿这套代码当底子纸面上的功能都能落地面试答辩时能讲清楚每个设计决策的理由就比绝大多数只会背八股文的候选人强多了。

相关新闻

MySQL并发更新安全吗?InnoDB行锁与丢失更新深度解析

MySQL并发更新安全吗?InnoDB行锁与丢失更新深度解析

1. 从一个经典面试题说起:这条SQL到底安不安全“update A set numnum? where id?”——这句话几乎每个后端开发都写过,但真要问它在并发场景下有没有线程安全问题,能答利索的人并不多。我第一次被问到这个问题是在一次内部技术评审上&#…

2026/10/13 11:25:45 阅读更多 →
中南大学数据库试题拆解:SQL、事务与索引三大考点复习指南

中南大学数据库试题拆解:SQL、事务与索引三大考点复习指南

简介:这份中南大学数据库试题资料面向高校计算机相关专业学生及数据库备考者,用于系统梳理课程重点与检验掌握程度。内容覆盖DBMS基础、三级模式结构、ER模型、关系模型与关系代数、SQL语言、索引机制、数据库保护(安全性、完整性、故障恢复、…

2026/10/13 11:25:45 阅读更多 →
Python本地PDF知识图谱构建全流程:从OCR到图谱检索

Python本地PDF知识图谱构建全流程:从OCR到图谱检索

简介:本资源是一套基于Python实现PDF智能处理与知识图谱应用的高分毕业设计源码,面向计算机、电子信息、数学等专业的本科生与研究生,解决非结构化PDF文档的自动化识别、关键信息抽取、知识建模及语义检索等核心问题,适用于课程设…

2026/10/13 11:25:45 阅读更多 →

最新新闻

计量芯片通讯校验和机制全解析:从原理到量产排障

计量芯片通讯校验和机制全解析:从原理到量产排障

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 12:09:58 阅读更多 →
C++日期类设计:运算符重载与天数转换的完整实践

C++日期类设计:运算符重载与天数转换的完整实践

1. 项目概述与需求拆解1.1 这个日期类到底在解决什么问题第一次看到“设计一个日期类Date,包括年、月、日等私有数据成员。要求实现日期的基本运算,如一日期加上天数、一日期减去天数、两日期相差的天数等”这个题目时,我第一反应是&#xff…

2026/10/13 12:09:58 阅读更多 →
PDF独立版zip安全使用指南:解压、参数与避坑

PDF独立版zip安全使用指南:解压、参数与避坑

简介:金山PDF独立版是一套由金山推出的专业PDF处理工具,集阅读、编辑、创建、转换、注释、表单填写与OCR识别于一体,适合办公人员、设计师、学生及企业用户应对日常文档处理需求,解决PDF文件难以修改、格式转换繁琐、协作批注不便…

2026/10/13 12:09:58 阅读更多 →
Scratch声音模块详解:声音播放与停止积木的用法、踩坑与同步异步思维

Scratch声音模块详解:声音播放与停止积木的用法、踩坑与同步异步思维

带娃做Scratch项目这几年,最常被问到的不是“怎么让角色动起来”,而是“为什么我的小猫没有声音”。A同学照着样例搭了一圈积木,一点绿旗,小猫一动不动,嘴巴一张一合就是不出声;B同学的小猫倒是响了&#x…

2026/10/13 12:09:58 阅读更多 →
线段树实战:区间赋值、查询与第k个零查找

线段树实战:区间赋值、查询与第k个零查找

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 12:09:58 阅读更多 →
GitHub热榜深度拆解:从项目筛选到自动化周报生成

GitHub热榜深度拆解:从项目筛选到自动化周报生成

又到了每周日晚上的固定节目:把 GitHub 热榜页面刷一遍,看看这七天社区里都在折腾什么。2026年10月4日这期周榜我反复看了好几遍,有几个项目上线没几天就冲到了总榜前列,也有一些老面孔靠着一波密集更新重新翻红。整体感觉是&…

2026/10/13 12:08:57 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →