一说到Java Web毕设很多同学的第一反应是图书管理、新闻发布这类经典题目做出来千篇一律答辩时老师问两句业务逻辑就卡住了。我这次做完的是SpringBootVue前后端分离的高校固定资产管理系统整套包括完整项目源码、SQL脚本和接口文档属于那种“业务有深度、技术栈完整、演示效果直观”的选题。如果你想找一份能真正跑起来、能讲清楚、能扛住答辩追问的毕业设计这个方向非常合适。这篇文章我不会只贴代码而是把为什么这么设计、关键模块怎么实现、项目怎么一步步跑起来、实际开发中踩过的坑全部讲透。1. 为什么选固定资产管理一个业务型毕设题目的真实价值1.1 这个系统到底管了什么业务先说清楚固定资产管理系统和普通库存系统的区别。管库存关心的是“进销存”关心数量、出入库流水高校固定资产管的是“资产的一生”——一台教学设备从采购入账开始被哪个院系领用、期间维修过几次、每年盘点时在不在、最后什么时候报废每一步都要留痕。资产一旦登记错位置或责任人年底盘点对不上账财务那边就没法交代这在学校里是真实存在的痛点。所以系统核心围绕资产的全生命周期来搭我把它拆成六个业务动作资产入账新采购设备登记台账录分类、编号、原值、存放位置、责任人。资产领用教职工提交领用申请院系管理员审批通过后资产状态变为“已领用”。资产维修设备故障登记维修单记录维修内容和费用期间资产状态变为“维修中”。资产盘点按院系或分类进行盘点确认“账实相符”还是“盘亏”。资产报废老旧或损坏设备发起报废申请审批后资产退出使用。数据统计按分类、部门、状态统计资产数量与金额支撑报表。这些动作串起来就是一个完整闭环。答辩时老师最常问的就是“你系统的业务边界在哪里”你把这六条讲清楚业务逻辑就站得住。1.2 同类选题对比为什么是它而不是图书管理或商城我做选题对比时列了一张表把自己的真实想法写出来常见毕设选题业务复杂度技术展示点答辩风险图书管理系统低基本是CRUD较少老师一眼望到底追问几次就空了在线商城中等但套路化购物车、订单、支付较通用容易和网上开源项目撞车固定资产管理中等偏高RBAC权限、状态机、审批流、报表业务逻辑能讲深有亮点商城项目我也考虑过但后来放弃了。商城的核心是商品和订单基本是“谁都能想到怎么设计”的通用模型演示时除了页面好看很难讲出业务深度。固定资产管理不一样它天然有角色分工——超级管理员、院系资产管理员、普通教职工——这就逼着你做权限模型它有状态流转这就逼着你做状态机和业务校验它还有“账实相符”这种盘点概念能把业务场景讲得接地气。做完之后我感觉这是同等工作量下“性价比”最高的选题方向。2. 技术选型SpringBootVue这套组合为什么是毕设的“最优解”2.1 后端为什么选SpringBoot和MyBatis-Plus后端我用的SpringBoot 2.7.x JDK8 MyBatis-Plus 3.5.x MySQL 5.7。这个组合在当前的Java Web毕设里接近“标准答案”了原因很朴素SpringBoot把原来SSH时代繁琐的XML配置全部自动化内嵌Tomcat打完jar包直接java -jar就能跑部署成本极低MyBatis-Plus则是在MyBatis基础上帮你把单表CRUD的活干完了不用再为每个实体写一套重复的Mapper方法。选MyBatis-Plus而不选Spring Data JPA我的理由是分页和条件查询。固定资产台账这种页面十个有八个都要做“按名称模糊搜索 按状态筛选 按分类筛选 分页”MyBatis-Plus的LambdaQueryWrapper写起来几乎是在用Java代码拼SQL条件非常直观而分页插件只需一个配置类就能启用。// MyBatis-Plus分页配置漏掉这个分页查询不会生效 Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }2.2 前端为什么用Vue2ElementUI而不是Vue3前端技术栈我选的是Vue2 ElementUI Axios Vue Router而不是Vue3 Element Plus。原因不是Vue3不行而是毕设追求的是“稳”。Vue2的生态资料最多遇到任何问题几乎都能搜到现成答案ElementUI组件库对表格、表单、弹窗、树形控件的封装非常成熟做管理后台基本不需要自己写CSS布局而且Vue2的语法对新手友好options API的思路就是把数据、方法、生命周期钩子分开放符合直觉。Vue Router负责页面跳转和路由守卫权限控制靠它完成。Axios负责向后端发请求我统一封装了一个request.js把baseURL、token注入、响应拦截都集中在一个文件里页面里只负责调用接口取数据代码量少了一大截。2.3 认证方案前后端分离为什么用JWT而不是Session这个问题答辩时几乎必问。前后端分离部署后前端和后端可能不在同一个域名端口下Session依赖Cookie的自动携带跨域时处理起来麻烦而且Session是服务端内存存储应用多实例部署时会话不同步。JWT是无状态令牌后端签发一个加密token给前端前端每次请求放进Authorization请求头后端解密校验即可天然适合前后端分离。// JWT校验拦截器核心逻辑 Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (OPTIONS.equalsIgnoreCase(request.getMethod())) { return true; // 跨域预检请求直接放行 } String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { throw new BusinessException(401, 未登录或token缺失); } Long userId JwtUtil.parseToken(token.replace(Bearer , )); UserContext.setCurrentUserId(userId); return true; }JWT也不是没有缺点最典型的是服务端无法主动让token失效。但毕设场景里用户量小能想到用JWT已经比用Session高一个层次了。3. 数据库设计固定资产系统的表结构拆解3.1 用户权限四件套user / role / menu / relation整套系统的用户模型是标准的RBAC基于角色的访问控制一共四张表sys_user用户表字段包括id、username、password、real_name、dept_id、phone、status。sys_role角色表预置超级管理员、院系资产管理员、普通教职工三个角色。sys_menu菜单表存储前端路由对应的菜单项包含菜单名称、路径、图标、父级id、排序号。sys_user_role和sys_role_menu用户与角色、角色与菜单的关联表。为什么中间要拐两层关联而不是直接在用户表里存一个角色字段因为“用户直接绑角色、角色绑菜单”这种设计以后想加一个新角色不需要改动任何用户数据只需要在sys_role_menu里配好菜单权限就行。这种可扩展性就是RBAC模型的核心价值。3.2 资产核心表从台账到报废一条线资产模块的六张表我按业务流程设计每张表解决一个业务动作表名核心字段对应业务asset_categoryid, category_name, parent_id资产分类支持多级asset_infoid, asset_no, name, category_id, original_value, status, dept_id, user_id, location, purchase_date资产台账主表asset_borrowid, asset_id, user_id, borrow_time, return_time, audit_status, audit_remark领用申请与审批asset_repairid, asset_id, repair_date, repair_content, repair_cost, status维修记录asset_scrapid, asset_id, scrap_reason, apply_user, audit_status报废申请asset_stocktakeid, stocktake_no, dept_id, stocktake_date, total_count, diff_count, remark盘点记录汇总asset_info是核心主表建议单独展开看一下关键字段设计CREATE TABLE asset_info ( id BIGINT PRIMARY KEY AUTO_INCREMENT, asset_no VARCHAR(32) NOT NULL COMMENT 资产编号, name VARCHAR(128) NOT NULL COMMENT 资产名称, category_id BIGINT COMMENT 资产分类id, original_value DECIMAL(12,2) COMMENT 原值, status TINYINT NOT NULL DEFAULT 0 COMMENT 状态:0在库 1已领用 2维修中 3待报废 4已报废, dept_id BIGINT COMMENT 使用部门id, user_id BIGINT COMMENT 当前责任人id, location VARCHAR(255) COMMENT 存放位置, purchase_date DATE COMMENT 购置日期, version INT DEFAULT 0 COMMENT 乐观锁版本号, created_time DATETIME, updated_time DATETIME );3.3 资产编号生成与状态机设计资产编号我在代码里用“ZC 年份 六位流水号”生成例如ZC202500001。生成逻辑是查当前年份已存在的最大编号取后六位加一再拼接。这块要注意并发问题两个请求同时拿到同一个最大号就会生成重复编号所以我用数据库的唯一索引兜底并且在生成服务方法上加了synchronized保证同一时间只有一个线程能取号。毕设规模下这样够用了。状态机是整个系统最容易讲出彩的地方。我在代码里定义了一个状态枚举明确列出合法流转路径在库0只能变更为已领用1或维修中2已领用1只能变为维修中2或在库0归还维修中2完成维修后回到在库0任何非报废状态都可以提交报废申请但必须走审批。非法流转直接抛业务异常拒绝落库。4. 后端核心模块实现从登录鉴权到资产流转4.1 统一返回体与全局异常处理前后端联调最怕各写各的返回格式前端取数据时一会儿data.data一会儿data.result人直接裂开。我一开始就定了统一返回体Result 结构非常简单{ code: 200, message: 操作成功, data: {} }所有Controller方法返回一律是Result前端Axios响应拦截器统一判断codecode为200就走到成功处理非200就直接弹出message。与之配套的是全局异常处理类。用RestControllerAdvice把所有异常兜住自定义的BusinessException对应业务规则错误比如“该资产不在在库状态无法领用”参数校验异常MethodArgumentNotValidException对应前端传参不合法最后的Exception兜底返回“系统繁忙请稍后重试”。这样做的直接好处是Controller里不需要写try-catch业务代码干净很多。4.2 登录与鉴权密码加密和Token签发用户表里的密码不能明文存这是答辩时必被问到的安全点。我用BCrypt对密码做哈希BCrypt的哈希串自带随机盐同一个密码每次加密结果都不一样比MD5加固定盐更安全。登录流程是接收用户名密码 - 查用户 - 校验BCrypt密码 - 生成JWT返回前端。JWT的生成我用的是jjwt库密钥写在application.yml里payload里只放用户id和角色编码有效期设两个小时。注意密钥不要太短项目里我配置的是一个32位以上的随机字符串并设置了重新登录后旧token失效的逻辑避免退登后token还能用。4.3 资产领用接口的业务校验细节资产领用是整个系统里业务逻辑最重的一个接口也是我写代码时最谨慎的地方。领用申请提交时后端要做三件事检查资产状态必须为在库0检查申请人信息是否完整写入领用记录并同时更新资产状态。这三步必须在一个事务里完成不然会出现“领用记录写了但资产没改状态”这种脏数据。Transactional(rollbackFor Exception.class) public void applyBorrow(BorrowApplyDTO dto) { AssetInfo asset assetInfoMapper.selectById(dto.getAssetId()); if (asset null) { throw new BusinessException(资产不存在); } if (asset.getStatus() ! AssetStatus.IN_STOCK.getCode()) { throw new BusinessException(该资产当前状态不可领用); } // 乐观锁更新资产状态防止并发重复领用 LambdaUpdateWrapperAssetInfo wrapper new LambdaUpdateWrapper(); wrapper.eq(AssetInfo::getId, asset.getId()) .eq(AssetInfo::getVersion, asset.getVersion()) .eq(AssetInfo::getStatus, AssetStatus.IN_STOCK.getCode()) .set(AssetInfo::getStatus, AssetStatus.BORROWED.getCode()) .set(AssetInfo::getVersion, asset.getVersion() 1); int rows assetInfoMapper.update(null, wrapper); if (rows 0) { throw new BusinessException(操作冲突资产状态已发生变化请刷新后重试); } // 插入领用记录 borrowMapper.insert(buildBorrowEntity(dto, asset)); }并发这块是很多毕设项目的重灾区。不加任何保护的话两个用户同时点领用都读到状态为在库然后都写领用记录资产就同时被两个人“领用”了。用乐观锁加状态条件更新后只有第一个请求能更新成功第二个更新行数为0直接被拦截。这一段逻辑给老师演示的时候是很有说服力的加分点。5. 前端核心页面与权限路由5.1 动态菜单和路由守卫怎么做前端权限控制不能只靠隐藏按钮真正的控制要落到路由层面。我的做法是登录成功后后端返回当前用户可见的菜单列表前端把它们注册成动态路由用户没有权限的路由根本不会出现在Vue Router里即使手动输入路径也会被路由守卫拦截。路由守卫写在router.beforeEach里核心逻辑是router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (!token) { if (to.path /login) return next(); return next(/login); } if (to.path /login) return next(/); if (!store.state.userInfo) { // 刷新页面后重新拉取用户信息和动态路由 store.dispatch(fetchUserInfo).then(() { next({ ...to, replace: true }); }); return; } next(); });这里有个容易被忽略的细节刷新浏览器后Vuex里的用户信息会丢失动态路由也没了所以必须在路由守卫里重新拉取用户信息再注册路由否则一刷新就跳登录页。5.2 资产台账、审批页和盘点页的实现思路台账页面是整个系统最核心的页面做成“左侧资产分类树 右侧表格”的布局。左侧树用ElementUI的el-tree点击一级分类右侧表格通过分类id模糊匹配查询该分类下所有资产。表格自带搜索栏支持资产名称关键字、状态下拉框、部门下拉框三个维度筛选还加了导出Excel的按钮。列表分页用的是el-pagination页码变化触发重新请求接口。审批页面做成“待办事项”的形式当前用户登录后接口只返回等待他审批的领用申请或报废申请每条记录右侧有“通过”和“驳回”按钮。审批通过会调用后端接口内部做资产状态更新驳回则只填写审批备注不改变资产状态。这个页面和台账页面组合在一起演示就构成了一条完整的业务闭环。盘点页面我做了简化功能是新建盘点任务、录入盘点差异备注、查看历史盘点记录。如果想做得有深度可以在盘点详情里做逐台资产的“账实比对”列表这个可以放到扩展篇去说。5.3 Axios封装和401统一处理Axios请求封装我单独建了一个request.js文件所有请求走同一个实例。请求拦截器里把token放进请求头响应拦截器里做统一逻辑service.interceptors.response.use( (response) { const res response.data; if (res.code 200) return res.data; if (res.code 401) { localStorage.removeItem(token); router.push(/login); } Message.error(res.message || 请求失败); return Promise.reject(new Error(res.message)); }, (error) { Message.error(网络异常请稍后重试); return Promise.reject(error); } );为什么要统一处理401因为token过期后后端会返回401错误码如果每个页面都单独判断很容易遗漏。统一在拦截器里清除本地token并跳到登录页所有接口自动生效。我实际测试时发现刷新页面后token丢失的问题就是在这一步通过重新拉取用户信息解决的。6. 接口文档怎么写才能直接对接联调6.1 一份合格接口文档该包含什么很多人写接口文档就是贴一个URL和几个参数名前端联调时来来回回问“返回字段是什么类型”“错误码有哪些”效率极低。我整理的接口文档每个接口固定包含七项信息接口名称、请求URL、请求方式、请求头、请求参数字段名、类型、是否必填、说明、响应示例、错误码说明。请求参数一定要细化到每个字段。比如“领用申请”接口的请求体要写清楚assetId是Long类型且必填、remark是String且可选。响应示例要给真实场景的JSON不要只写个“成功”。错误码要单独列一张表说明什么情况返回什么码。这些内容虽然写起来琐碎但对联调效率的提升是立竿见影的。6.2 三个核心接口的文档示例我这里拿出三个有代表性的接口文档片段给大家参考。登录接口项目内容接口名称用户登录请求URL/api/auth/login请求方式POST请求参数username: String必填password: String必填响应示例{code:200,message:操作成功,data:{token:eyJhbGciOiJIUzI1NiJ9...,userInfo:{id:1,username:admin,realName:管理员,roleCode:SUPER_ADMIN}}}错误码1001用户名或密码错误资产分页查询接口项目内容接口名称分页查询资产台账请求URL/api/asset/page请求方式GET请求参数pageNum: int默认1pageSize: int默认10name: String可选status: Integer可选categoryId: Long可选响应示例{code:200,message:操作成功,data:{records:[...],total:128,pageNum:1,pageSize:10}}错误码无提交领用申请接口项目内容接口名称提交资产领用申请请求URL/api/borrow/apply请求方式POST请求头Authorization: Bearer {token}请求参数assetId: Long必填remark: String可选响应示例{code:200,message:领取申请提交成功,data:null}错误码2001资产不存在2002资产当前状态不可领用2003操作冲突请刷新重试6.3 接口文档的维护方式接口文档我用Knife4j自动生成做了主要接口说明但答辩时还是习惯用一份独立的Markdown接口文档。理由是Knife4j自动生成的文档适合开发中查但格式偏机器化而独立文档可以把接口按业务模块分组加上设计思路和注意事项答辩演示时更好讲。维护接口文档有个实际经验每次后端接口一改马上同步更新文档不要攒到最后一次性补。项目后期接口改了七八版如果不是当时就更新最后补文档的时候根本记不清改了什么。7. 从零跑通整个项目环境准备与启动步骤7.1 环境清单我把整个项目跑通需要的东西列成一个清单照着装就行JDK 8或11必须配置JAVA_HOME环境变量。Maven 3.6.3以上用来管理后端依赖。Node.js 14或16用来跑前端Vue项目。MySQL 5.7或8.0用来导入数据库脚本。开发工具后端推荐IDEA前端用VS Code也可以统一用IDEA。7.2 SQL脚本导入和配置文件修改项目里提供的sql脚本会创建一个gy_asset数据库包含建库语句、建表语句和初始化数据。初始化数据我预置了三个角色、一个超级管理员账号账号admin初始密码admin123还塞了几条资产分类和资产台账样例数据这样导入后登录就能看到效果。导入步骤很简单Navicat里新建数据库gy_asset字符集选utf8mb4然后右键运行SQL文件选择脚本执行即可。执行完建议先看一下asset_info表里有没有样例数据确认脚本没执行错。后端启动前要改application.yml里的数据库配置server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/gy_asset?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的数据库密码 mybatis-plus: global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0这里有个特别容易踩的坑MySQL 8.0的驱动类名是com.mysql.cj.jdbc.DriverMySQL 5.7用com.mysql.jdbc.Driver也可以跑但5.7的旧驱动到8.0会直接报ClassNotFoundException。你要是本地装了MySQL 8驱动类名一定要写带cj的版本。7.3 前后端启动命令后端在IDEA里直接运行Application启动类即可或者用命令行mvn spring-boot:run看到“Started Application in x.xxx seconds”就说明启动成功。前端进入项目目录执行npm install npm run serve这里我给新手一个建议npm install如果卡在fetchMetadata卡了很久大概率是网络问题换成淘宝镜像源npm config set registry https://registry.npmmirror.comnpm install装依赖本身就可能耗掉十几分钟属于正常现象别中途强制中断等它装完。7.4 启动过程中最常见的四个报错我把实测遇到过的启动问题按概率排个序报错现象原因解决方式Access denied for user rootlocalhost数据库账号密码错误检查application.yml里username/passwordUnknown database gy_asset数据库没建或没导入SQL执行SQL脚本或先create databasePort 8080 was already in use8080端口被占用改server.port或者杀占用进程ERR_CONNECTION_REFUSED / 跨域报错前端访问后端被拦截开发环境用Vue CLI的proxy代理或后端配置CORS跨域是前后端分离必过的坎。最简单的方式是后端写一个CorsFilter配置类允许本地前端的http://localhost:8081来源跨界访问同时必须放行OPTIONS预检请求。如果你用Vue CLI开发模式也可以在vue.config.js里配置代理把/api开头的请求都转发到localhost:8080这样前端请求就是“同源”的生产环境再用Nginx做反向代理。我项目里开发环境用的是代理方式演示时比较干净。8. 我实测踩过的坑与最终优化建议8.1 踩坑记录汇总做过这个项目后我把踩过的坑整理成了一张排查表每个坑都是真实触发过的问题触发场景根因解决办法前端Long类型id精度丢失资产详情里点查看跳转的id最后几位变成0后端返回的Long id超过JS Number安全范围统一将Long序列化为字符串日期字段返回乱码或格式不对列表里日期显示成时间戳数字Jackson默认把Date转成时间戳全局配置JsonFormat(patternyyyy-MM-dd HH:mm:ss)MyBatis-Plus分页结果total为0分页查不出总记录数没有配置MybatisPlusInterceptor分页插件补上分页插件配置类修改密码后老token还能用用户改密后旧token请求正常通过JWT无法主动失效服务端维护账号token版本号领用同时提交导致状态错乱两个账号同时领用同一资产缺少并发控制乐观锁状态条件更新刷新页面后路由丢失从资产页刷新直接跳登录动态路由在刷新后未被重新注册路由守卫里重新拉取用户信息及菜单我印象最深的是Long型id精度丢失那个问题。列表接口返回的资产id是数值型前端JavaScript处理超过9007199254740991的数字时精度会丢失导致你查看的是id1的资产跳转过去可能变成了id1000000000000001。这个坑在数据量大了之后百分百会出现。解决办法是配置Jackson将Long全局转为StringBean public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { return builder - builder .serializerByType(Long.class, ToStringSerializer.instance) .serializerByType(Long.TYPE, ToStringSerializer.instance); }8.2 上线前一定要做的三件事如果这是要提交到学校服务器展示的或者打算放到简历上的有三个地方一定要处理。第一把数据库里初始管理员密码改掉不要用admin123这种弱口令答辩现场有人翻你数据库配置看到密码都会问一句安全设计第二把application.yml里的数据库配置抽离到环境变量里至少不要在代码里暴露一个真实的生产密码第三给后端加日志记录特别领用、审批、报废这几个关键操作要记录操作人和操作时间这是审计需求也是答辩时讲“系统可追溯”的底气。8.3 想拿高分可以扩展的方向这套系统做完其实只用了它七成功力还有几个方向可以拿去当亮点加分。一个方向是给每台资产生成二维码用ZXing库把资产编号和基本信息编成二维码打印后贴到设备上手机扫码就能看到这台资产的台账、维修记录和责任人这是现在很多单位资产管理的实际做法。另一个方向是数据可视化用ECharts做一个首页统计面板展示各部门资产数量占比、资产分类金额分布、本月新增与报废对比图演示放在登录后首页视觉效果非常直观。还有一个方向是用EasyExcel把台账数据做成批量导入导出管理员从Excel模板批量登记资产这个功能在实际场景中比单条新增实用得多。我个人在完成这套系统后最大的体会是一个毕设项目能不能拿高分不在于用了多少新技术而在于业务逻辑能不能自洽、异常情况有没有考虑全、演示过程能不能讲成一条完整故事。固定资产管理这个题目恰好给了这些可能性。如果你正在做类似的选题建议把状态流转、权限控制、并发安全这三个点优先做好这三点是评审老师最容易深挖、也最能展示工程能力的地方。
企业数字化 ERP 产品动态
相关推荐
内蒙古路网shp数据处理实战:从坐标系到格式转换全解析 简介:内蒙古路网矢量数据(shp格式)是一份面向GIS开发者、交通规划师与科研工作者的空间数据集,以线矢量要素完整描绘自治区内高速、国道、省道、县道等道路网络的几何路径与属性信息,可用于地图制图、交通流量分析、环… · 2026/9/25 3:37:17
内存取证实战:Volatility2/3完整命令与恶意痕迹分析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:37:17
@urql/svelte 版本演进全解析:从 operationStore 到函数式 Store API 前端 【免费下载链接】urql The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow. 项目地址: https://gitcode.com/gh_mirrors/ur/urql 点击查看 免费下载 urql/svelte 是 urql 生态中为 S… · 2026/9/25 4:04:14
Moto 贡献者开发实战指南:命名规范、测试编写与分页器、状态机等核心开发技巧 Mock测试 【免费下载链接】moto A library that allows you to easily mock out tests based on AWS infrastructure. 项目地址: https://gitcode.com/gh_mirrors/mo/moto 点击查看 免费下载 本篇指南面向所有想为 Moto(AWS 基础设施模拟测试库… · 2026/9/25 4:04:14
Livox ROS2驱动编译部署指南:从零到一避开所有坑 说出来你可能不信,一个号称“只 clone 就能编译”的激光雷达 ROS2 驱动,让我在编译阶段就折腾了两个晚上。拿到 Mid-360 那天,我原本的计划是半小时跑通:装依赖、克隆仓库、colcon build、启动 RViz 看点云。结果是colcon build那… · 2026/9/25 4:04:08
STM32+4G模块+MQTT接入阿里云物联网平台完整指南 1. 方案选型与整体架构拆解1.1 为什么是STM324G模块MQTT阿里云做物联网设备接入这件事,最常见的需求就是:现场设备采集数据,我要在千里之外的电脑上或者手机App上实时看到这些数据,必要时还能远程下发指令。这个需求落到硬件端&am… · 2026/9/25 4:04:08
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37