news 2026/10/4 1:34:34

Java+微信小程序上门维修系统实战:从架构到部署全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java+微信小程序上门维修系统实战:从架构到部署全解析

简介:这是一份基于Java Spring Boot与微信小程序的上门维修系统完整源码,面向计算机专业学生、毕业设计者及Java全栈开发者,可用于学习维修服务预约、订单管理、评价闭环等典型业务场景。资源压缩包共1248个文件,大小约20.07MB,文件类型覆盖广泛:Java负责后端接口与业务逻辑,Vue构建后台管理页面,wxml/wxss/js组成小程序前端,SQL脚本用于初始化MySQL数据库,另含Maven配置与bat启动脚本,整体结构清晰,适合直接导入开发工具运行。功能包含用户注册登录、维修信息展示与下单、维修记录管理、服务评价、广告收藏,以及管理员对用户、订单、评价、广告等模块的增删改查,基本形成一个完整的上门维修业务闭环。目前已有119人学习下载,若用于课程设计或毕业设计,可直接参考其前后端交互方式、权限控制思路与数据库设计,也可在此基础上进行二次功能扩展。

1. Java + 微信小程序做上门维修系统:一套能跑通全流程的毕业设计与实战项目

如果你刷到过「基于Java和微信小程序的上门维修系统.zip」这个标题,大概率是两种情况:要么你在找课程设计或毕业设计的现成案例源码,要么你准备给物业、家电售后或本地生活平台搭一套预约维修的演示系统。这套东西的实际形态并不复杂——用户通过微信小程序发起维修工单,后台 Java 服务接收、派单或抢单,维修师傅在小程序端更新服务状态,订单完成之后还能做评价和统计,是一套典型的「小程序 + Spring Boot + MySQL」应用。它不涉及高并发,不涉及分布式事务,但把登录鉴权、订单状态流转、角色权限、支付对接这些真实业务里一定会碰到的东西完整串了一遍,所以它也是很多 Java 开发工程师面试前拿来复盘的项目素材。

这篇文章不会去吹这个 zip 里的代码写得多好,而是按一线工程的视角,把「拿到这套源码后怎么跑起来、订单状态机怎么设计、前后端联调时哪些配置必须改、上线前哪些坑一定会踩」拆开讲透。新手照着能一步步把项目跑通,熟手就着这个业务模型也能看出这套系统的边界在哪,值不值得往自己的项目里搬。

2. 技术选型与整体架构:为什么是 Spring Boot + 原生小程序,而不是 uniapp 或纯 H5

2.1 前后端分离的经典组合:Spring Boot + MyBatis + JWT

上门维修系统这类业务,后端选型几乎不需要纠结。Spring Boot 负责接口层,MyBatis(或 MyBatis-Plus)负责数据库访问,MySQL 存业务数据,JWT 做登录态,这是国内 Java 课程设计和中小型落地项目里最常见的组合,资料多、上手快、踩过的坑网上全都有记录。拿到手先确认三件事:JDK 版本、Spring Boot 版本、MySQL 版本。JDK 8 对应 Spring Boot 2.x,JDK 17 配 Spring Boot 3.x,别一上来就把代码跑崩在版本兼容上。

这套系统的典型分层是 Controller → Service → Mapper,Controller 层只做参数接收和结果封装,Service 层处理订单状态流转这种核心业务逻辑,Mapper 层跟数据库打交道。用户端和师傅端虽然都在小程序里,但后端接口会按角色区分权限,比如用户能创建订单,师傅才能更新维修进度,管理员能看到全部订单列表。这些角色判断放在 JWT 过滤器里统一做,不会散落到每个接口里单独判断。

一个让我比较意外的点是,这类源码项目里很多会把「师傅管理」「服务分类管理」也做成小程序内页面,而不是独立的管理后台。这种做法在后端实现上少写一套 Web 管理端,但管理操作在小程序里确实不太好用。如果你打算把这套系统拿去做真实运营,建议后端预留出管理接口,后面要拆独立后台时前端换个壳就行,业务层完全不用动。

2.2 小程序原生开发 vs uniapp:先想清楚要不要做多端

用原生微信小程序开发的好处是,页面渲染、组件生命周期、wx.request 网络请求都是第一手 API,调试时遇到问题搜索到的答案基本能直接用,不存在编译链带来的额外黑匣子。缺点也很明显:代码只能在微信里跑,将来要出支付宝小程序或 App,整套前端页面逻辑基本要重写一遍。这就是按标题选型时的一个重要决策点——如果这个系统做完之后只服务于微信生态,原生开发足够;如果预期还要扩展其他端,我一般会建议改成 uniapp,Vue 语法写页面,一套代码打包多端。

在适配问题上,原生开发也有自己的血泪经验。不同手机的顶部导航栏高度不一样,小程序里用 wx.getSystemInfoSync() 获取状态栏高度做自定义导航栏时,测试机适配了 iPhone,Android 中端机上一跑就出问题。还有底部安全区的问题,维修师傅在手机上点「开始服务」「完成订单」这些按钮,如果按钮被 iPhone 底部黑条遮住一半,用户会直接放弃操作。这些细节在小程序开发者工具上模拟不出来,但真机预览时必翻车。

联调阶段,前后端不在同一个域名下,小程序默认会拦截请求。开发时的解法是:在微信开发者工具右上角「详情 → 本地设置」里勾选「不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书」。注意,这个选项只对开发者工具和「预览」模式生效。用真机预览时,手机端的微信也会拦截未配置域名的请求,这时候要么在后端临时开一个局域网 IP 加端口供手机访问,要么就把接口域名先配到小程序管理后台的「服务器域名」里。

2.3 把源码包跑起来:先看配置,再启动,最后调页面

拿到源码包后不要急着点启动。重点检查 application.yml(或 application.properties)里的数据源配置、Redis 配置(如果用了)和小程序 appid。这个顺序能避免至少半小时的无效排错。数据源配置里最常见的坑是 MySQL 连接串没带时区参数导致的时间报错,以及数据库密码不一致导致的连接失败。在配置里显式加上几个关键项,能省掉很多后续排查成本。

后端部分常见的启动流程是:先在 MySQL 里把数据库建好,然后执行项目里的 SQL 脚本初始化表结构,改好 application.yml 里的连接信息,启动 Spring Boot 主类,确认控制台没有红色报错。小程序端则用微信开发者工具「导入项目」,填入小程序的 AppID(没有就选测试号),接口地址改成后端服务器的 IP 加端口,编译运行后先跑登录流程,再看订单列表是否加载出来。

这里有一个需要特别注意的边界:这类源码包里的 SQL 脚本,表结构往往是为了跑通演示设计的,字段命名可能不规范,但也别急着改。先把系统跑通,确认数据能正常读写,再根据你的实际业务去调整表结构。许多新手一上来就看字段名不顺眼,改了表又去改 Mapper 里的 SQL 映射,结果连锁报错一大片,反而把自己绕进死胡同。

提示:环境变量里 JAVA_HOME 配的是 JDK 8,但 IDE 加载的构建工具用的是 JDK 17,这种不一致很容易导致编译报错(比如 Lombok 注解处理失败),这是这类源码项目启动时最常见也最玄学的翻车点。启动前先核对系统的 java -version 和项目要求的版本一致。

3. 订单状态机与核心数据模型:上门维修系统的业务灵魂

3.1 看表结构也是在读业务:五张核心表能跑通一个完整订单

这类系统的业务逻辑看起来功能多,落到数据库层面,真正核心的表就那几张。用户表存微信端登录用户的基础信息;师傅表存维修人员的姓名、技能类别、接单状态、评分;服务分类表存维修项目的分类层级,比如「家电维修 → 空调维修 → 挂机不制冷」;订单表是整个系统的主表,记录谁下的单、哪个师傅接的、故障描述、地址、预约时间、服务状态;评价表在订单完成后由用户对师傅进行打分和文字评价。

我用表格把核心字段和大致的字段职责列一下,方便你在对照源码表结构时快速对应上:

表名关键字段说明
t_userid, openid, nickname, avatar, phoneopenid 是微信用户唯一标识,务必加唯一索引
t_masterid, user_id, skill_type, status, score师傅关联用户表的 user_id,status 控制是否可接单
t_categoryid, parent_id, name, sortparent_id 为 0 时是一级分类,支持多级层级
t_orderid, user_id, master_id, category_id, fault_desc, address, expect_time, status, amountstatus 是状态机核心字段,amount 以「分」为单位
t_evaluationid, order_id, score, content, imgs一个订单只允许一条评价,order_id 需唯一

订单表里有两个字段要重点理解:status 和 amount。status 记录当前订单在哪个状态,amount 记录维修费用。很多新手在金额字段上直接用 decimal,再在 Java 侧用 BigDecimal 计算,这本身没问题,但如果你在代码里看到 double 类型,就要小心了。浮点数参与金额运算会产生精度误差,财务统计差了整分钱很难查。规范做法是数据库用 int 存储「分」,接口返回时转成「元」或者直接返回分为单位,让小程序端自己处理展示。这是这类系统里一个很值得修正的点,改起来不费事,但能避免后面做统计报表时的很多麻烦。

3.2 订单状态流转:待受理、已接单、服务中、待支付、已完成

上门维修订单的状态不能随便改,用户不能把「待受理」的订单直接改成「已完成」,师傅也不能跳过维修环节直接收钱。这里必须有状态机来控制流转路径。常见的状态序列是:待受理 → 已接单 → 服务中 → 待支付 → 已完成,外加两个支线:用户取消订单和超时未受理自动取消。

状态枚举用 Java 写出来大概是这个样子:

public enum OrderStatus { PENDING_ACCEPT(0, "待受理"), ACCEPTED(1, "已接单"), IN_SERVICE(2, "服务中"), PENDING_PAY(3, "待支付"), COMPLETED(4, "已完成"), CANCELED(5, "已取消"); private int code; private String desc; public int getCode() { return code; } public String getDesc() { return desc; } public boolean canTransferTo(OrderStatus target) { // 定义合法流转路径 return Arrays.asList(TRANSITIONS.get(this)).contains(target); } OrderStatus(int code, String desc) { this.code = code; this.desc = desc; } }

代码里的 TRANSITIONS 可以理解为一个 Map,每个状态对应一个「只允许流转到哪些状态」的列表。为什么要在 Service 层加这一层判断,而不是直接在 Controller 里写 if?因为状态流转是订单系统的核心逻辑,把它收敛在枚举或 Service 层里,既能避免上层接口随意改状态,也方便后面做数据统计时看清楚每个订单经过的完整路径。这套思维本质上就是在用代码把数据一致性约束住,避免出现订单状态数据错乱这种修起来极麻烦的问题。

我在看过不少源码后,发现一个非常常见的翻车点:订单状态在t_order表里只存了当前状态值,但这个状态是怎么一步步走过来的,完全没有历史记录。一旦用户投诉「我没点过确认但订单自动完成了」,后台就抓瞎了。解决方法是加一张 t_order_log 表,每次状态变更都插入一条记录,包含订单号、旧状态、新状态、操作人、操作时间。这张表现在不显眼,但到真实运营阶段,它会成为客服排障和业务审计的重要依据。

3.3 师傅匹配与抢单:排序和并发是这边的重头戏

师傅分配是这个系统里最有意思的部分,多数源码项目做的是「抢单制」:新订单进入待受理池,师傅端小程序轮询或下拉刷新看到待受理列表,点「抢单」。这个模式实现简单,也不用做复杂的派单算法,但前提是同一时刻只能有一个师傅改单成功。如果两个师傅同时点抢单,后端都先查「订单状态=待受理」,甲师傅把状态改成已接单,乙师傅再改一次,后执行的更新就会把订单覆盖到乙名下,用户就遇到了「谁抢到了」的困惑。

防护做法并不需要引入消息队列或分布式锁——这类系统的并发量用数据库层面就能处理。把更新语句写成条件更新:

UPDATE t_order SET master_id = #{masterId}, status = 1, accept_time = NOW() WHERE id = #{orderId} AND status = 0

如果 update 返回的影响行数等于 1,说明这次抢单成功;返回 0,说明状态已被别人改过,订单被抢走了。这是典型的乐观锁思路,不锁表、不加复杂中间件,一条 SQL 就把并发问题化于无形。对刚入门的朋友来说,这是理解「并发控制在数据层解决,而不是靠应用层攔截」最直观的案例之一。

师傅排序这块逻辑虽然简单,但也引出了一个小问题:列表是按距离优先、评分优先,还是按接单量排序?源码项目的常见做法是后端拿到订单地址的经纬度,计算出当前师傅位置与订单地点的距离,按距离近到远、评分高到低调序。这里用得上 Java 的排序操作,把师傅列表放进集合里按多条件排序,再返回给小程序。不过很多演示版本会偷懒,直接按师傅的注册时间排序——反正不涉及真实调度,业务上跑得通就行。如果你想拿这套系统做答辩亮点,把「距离 + 评分 + 本月接单量」的排序策略讲清楚,比堆十个功能页面更有说服力。

4. 前后端联调落地:从微信登录到订单列表加载更多

4.1 微信登录换 token:openid 从哪来,token 存哪去

微信小程序的登录流程,几乎可以当作所有小程序项目的模板。小程序端调用wx.login()获取一个临时登录凭证 code,把它发给后端;后端拿着 code 调用微信接口换 openid 和 session_key;后端生成自己的 token(用 JWT),返回给小程序;小程序把 token 存入本地缓存,后续请求都在请求头里带上。

小程序端这一段代码长这样:

wx.login({ success(res) { if (res.code) { wx.request({ url: 'https://your-server.com/api/user/login', method: 'POST', data: { code: res.code }, success(resp) { const { token, userInfo } = resp.data.data wx.setStorageSync('token', token) wx.setStorageSync('userInfo', userInfo) } }) } } })

这里有几个细节容易被忽略。code 只能用一次,后端换 openid 失败后不能拿同一个 code 重试;openid 是用户在指定小程序下的唯一标识,同一用户在不同小程序下的 openid 不同,后端表结构里如果只有一个 openid 字段且全系统共用一套用户体系,就会跨端串号。很多源码项目的后端并没有真正调用微信的 jscode2session 接口,而是把前端传入的 code 直接当 openid 入库,这种实现只适合做演示,用于真实环境会出安全问题,因为任何人都可以伪造 code 来批量创建用户。

登录成功后的 token,小程序端也要妥善管理。常见做法是存在 storage 里,然后在wx.request的封装中统一加请求头:当 token 过期或后端返回 401 时,清理本地缓存并强制跳转到登录页。不少源码项目在这里偷懒,只在每个页面的 onLoad 里判断有没有 token,导致用户在使用过程中登录态静默失效,接口开始报错,页面却没有任何提示——这是体验感最差的一类故障。

4.2 创建维修订单:表单、校验、入库,一个环节都不能省

用户在维修页面选择故障分类,填写故障描述、联系地址、期望上门时间,然后提交订单。这个流程在后端对应的是一个 Post 接口,接单后生成一条待受理状态的订单记录。后端接口代码大致是:

@PostMapping("/api/order/create") public Result createOrder(@RequestBody OrderCreateDTO dto, HttpServletRequest request) { // 1. 从 Token 里解析用户身份 Long userId = JwtUtil.getUserId(request.getHeader("Authorization")); // 2. 参数校验(分类是否存在、描述长度、地址是否为空) if (dto.getCategoryId() == null || dto.getAddress() == null) { return Result.error("参数不完整"); } // 3. 组装订单对象,初始状态为待受理 Order order = new Order(); order.setUserId(userId); order.setCategoryId(dto.getCategoryId()); order.setFaultDesc(dto.getFaultDesc()); order.setAddress(dto.getFaultDesc()); order.setExpectTime(dto.getExpectTime()); order.setStatus(OrderStatus.PENDING_ACCEPT.getCode()); // 4. 入库并返回订单号 orderService.createOrder(order); return Result.success(order.getId()); }

创建订单虽然是整条业务链路里最简单的一步,但有一个小坑:参数校验别只在前端做。小程序端可以校验「故障描述必须填写」「手机号格式正确」这些规则,但后端必须再校验一遍,因为小程序可以被绕过,直接调接口就能伪造请求。后端服务面向的客户端不止小程序一个,任何校验只做在前端,就等于没做。这个观点在做 Java 面试项目复盘时尤其值得讲,能体现出你确实考虑过安全问题。

4.3 订单列表分页与加载更多:onReachBottom 和后端三件套

订单列表页是用户最常看的页面,数据一多就必须分页。小程序端onReachBottom触底加载更多是标准做法:

onReachBottom() { if (this.data.hasMore && !this.data.loading) { this.setData({ page: this.data.page + 1 }) this.loadOrders(this.data.page) } }

对应的后端接口需要三个参数:page、pageSize、mastersId 或 userId。返回值是当前页数据加一个 hasMore 信号。实践中很多源码项目直接用 MyBatis-Plus 的分页插件,调用Page对象就能拿到总条数和列表数据,再把hasMore算好返回给前端。要注意的是,第 5 章里会提到的一个常见毛病——分页参数从第 1 页开始还是从第 0 页开始,后端跟小程序定义不一致会导致首页被跳过或重复加载。前后端在联调前先把它对齐,能省掉半天排查时间。

订单列表里的每一项还可能展示一个状态标签,比如「待受理」「服务中」「已完成」。这些状态文案在小程序端通常会维护一个映射表,跟后端接口返回的 status 字段对接。有的源码会把状态文案写后端返回,这样小程序端不用同步更新,但也意味着每次改状态文案都要动后端代码。我更倾向后端返回状态码、前端维护文案,毕竟文案是展示层面的东西,应该让前端控制。

提示:真机预览时如果发现列表加载到一半,下拉加载更多就再也不触发了,先看是不是onReachBottom触发距离设置得过小,或者页面高度被某个弹层挡住了,这类问题多数不是后端接口的问题。

5. 避坑专章:跑通这套系统的五个经典拦路虎

5.1 真机预览时接口全部请求失败,开发者工具里却一切正常

现象:模拟器上订单列表、登录都能跑通,但点「预览」生成二维码,用手机一扫,所有接口返回失败,页面白屏或一直转圈。

原因:开发者工具勾选了「不校验合法域名」,这个配置只对工具环境生效。真机预览时微信客户端启用正式的安全校验,凡是请求的域名没在小程序后台配置过,统统拦截。这是小程序开发最普遍的认知缺口,也解释了为什么很多人第一次真机调试时会一脸懵。

解决:把后端接口的域名加进「微信公众平台 → 开发 → 开发设置 → 服务器域名」里的 request 合法域名列表,域名还必须具备有效的 HTTPS 证书。在真正备案和配置完成之前,开发阶段可以打开开发者工具里的「预览模式」搭配「不校验合法域名」在本地测试,但这只能缓解一时。这个配置越早做越好,别拖到上线前几天才想起来,小程序管理后台的域名审核周期和 HTTPS 证书申请周期都不短。

5.2 接口偶发返回 10002 / 401,看日志毫无收获

现象:用户反馈订单提交失败,接口返回类似 10002 的错误码,后端日志里没有明显的异常堆栈,前端只看得到「请求失败」。

原因:这里要分两种情况排查。如果 10002 是前端wx.request层返回的网络错误码,常见原因是请求超时或 DNS 解析失败,跟后端代码不一定有关系。如果 10002 是后端业务层返回的,通常是登录态过期,鉴权过滤器把请求拦截了,但前端没有处理好 token 过期后的跳转逻辑,用户停留在页面上操作,每次请求都被打回。

解决:前端统一封装wx.request,在响应拦截里判断业务状态码。遇到 401 或登录态失效码,先清空 token 并跳转登录页,而不是把错误信息直接透出给用户。后端这块排查时,先用 curl 或者 Postman 直连接口,确认是不是 token 校验逻辑在作怪。很多看起来莫名其妙的 10002,最终定位都是 token 过期或鉴权 header 名称对不上。

5.3 两个师傅同时抢一单,后台出现两条受理记录

现象:后台订单查询里,同一订单号的 master_id 被两个师傅先后写入,或者订单详情里出现了多条处理记录,数据乱套。

原因:抢单接口的逻辑是「先查询订单状态,再更新订单状态」,而非「直接按条件更新」。查询和更新之间有时间差,两个并发请求都读到了「待受理」,然后各自更新成功,导致同一订单被多人认领。这个问题的本质是并发控制没做好,和用不用集群、用不用分布式锁无关,单机部署一样会出现。

解决:把「查询再更新」改成第 3.3 节写的条件更新 SQL,或者用数据库行锁(SELECT ... FOR UPDATE)。条件更新是轻量方案,适用于绝大多数场景;行锁适合要同时读取订单详情做更多业务处理的场景。修完这个逻辑之后,最好在测试环境用两个账号同时抢单压一下,验证只有一方成功。

5.4 金额用 double 结算,对账差了 0.01 块钱

现象:订单金额、师傅结算费用在统计时出现尾数差异,比如一笔 29.99 元的订单,统计出来变成 29.9900001。

原因:Java 的 double 和 float 在十进制小数运算上存在精度丢失问题,这在金额计算场景里是硬伤。源码项目如果直接用 double 金额字段,对账必出问题,只是数据量少时不易察觉。

解决:数据库字段用 int 或 bigint 存「分」,Java 层用 long 或 int 运算,前端展示时再自行决定要不要转成「元」。如果系统已有金额字段且类型是 decimal,统一改成以分为单位的整数存储。这个修改会波及订单表、结算表和所有金额相关的接口,但一旦改完,以后做财务报表就不用再担心精度问题了。这种从「元」改成「分」的重构,是花一天时间换一年安心的最佳投入。

5.5 本地能连数据库,上线后接口报「无法连接数据库」

现象:本地开发时后端和数据库在同一台电脑上,一切正常。部署到云服务器后,接口频繁超时,日志里出现数据库连接失败或连接池耗尽。

原因:云服务器的数据库连接串没改,或者数据库端口只对本地开放;另一类常见情况是数据库连接池配置过小,订单高峰期连接被占满。很多源码项目默认把连接池配置写在开发环境配置里,部署时容易遗漏。

解决:把数据库地址、账号、密码放到独立的配置文件里,部署时用环境变量覆盖。连接池配置也别照抄默认值,根据自己的业务量调整maximum-pool-size和minimum-idle。上线前在服务器上先跑一遍接口自测,确认数据库连通性,别直接引入流量再发现连不上库。

6. 进阶优化与验证技巧:跑通之后,让这套系统在答辩或面试里立得住

系统跑通只是开始,要让这套上门维修系统在答辩、面试或演示时有说服力,还得往深度做两件事:一是业务验证,二是数据可视化。

业务验证方面,我习惯的做法是准备一套完整的端到端测试流程:用户在小程序下单 → 师傅端看到待受理订单 → 抢单 → 更新维修状态 → 用户端订单状态同步变化 → 付款 → 评价。每一步都截图留存,这在毕业设计答辩或给甲方做演示时是非常有用的证据。别光靠嘴上说「测试过」,把演示路径完整走一遍,能发现很多静态代码里看不出来的联调问题。

数据可视化是让系统看起来「有完成度」的加分项。在后台或管理端加一个订单统计面板,统计今日订单量、师傅完工单数、平均上门时长、用户好评率。这些数据从订单表、师傅表、评价表里用简单的 SQL 聚合即可查出来。比如某分类下师傅的平均评分、不同时间段的下单分布,这些统计结果能反映出系统已经沉淀了实际业务数据,也对之后做派单调度优化至关重要——距离和评分是最直观的派单权重因子。

从源码项目到面试项目,有几个点值得深入准备:订单状态机的设计原因和可扩展性,抢单并发控制策略对比,金额精度处理方案,以及 token 登录态的完整生命周期管理。把这些问题讲清楚,比说出「我写过 50 个接口」要更有说服力。面试官问到「如果订单量大起来怎么办」,可以从分表分库、Redis 缓存热点数据、MQ 削峰三个方向去谈,不一定真的实施,但思路要清晰。

我自己的习惯是拿到一套源码后先跑通,再改坏一个功能,调试好了就理解了它的边界。这个小习惯帮我避开了很多「看着能跑、实际一改就崩」的源码坑。如果你正在折腾这套上门维修系统,建议先按本文第 2 章把环境顺好,再按照第 3 章的状态机逻辑梳理代码,遇到并发和金额的坑也别慌,照着第 5 章改一遍基本都能化解。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 1:34:34

GSEApy富集分析原理与KEGG通路深度解构实战

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

作者头像 李华
网站建设 2026/10/4 1:34:34

STM32F746ZG驱动SPI MRAM:工业级嵌入式存储的选型与实现

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

作者头像 李华
网站建设 2026/10/4 1:33:57

Joinpoint回归与AAPC:疾病负担趋势分析原理与实操指南

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

作者头像 李华
网站建设 2026/10/4 1:33:41

MRAM替代EEPROM/Flash:STM32L031与MR25H40CDF的掉电保存设计

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

作者头像 李华
网站建设 2026/10/4 1:33:10

STM32 HAL库与标准库代码级差异深度解析

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

作者头像 李华
网站建设 2026/10/4 1:33:09

从零搭建AI工程:数据链路、模型部署与可观测性实战指南

用一篇博文的体量,把“ai-engineering-from-scratch”这个命题拆开揉碎。这不仅仅是一个项目名称,更是一条从零开始建立 AI 工程能力的完整路径。我结合自己做过的大大小小的项目,从环境搭建、数据准备、模型训练一直聊到部署监控和团队协作&…

作者头像 李华