news 2026/10/1 19:17:25

Java+小程序实验室管理系统实战部署指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java+小程序实验室管理系统实战部署指南

简介:这是一套面向计算机专业本科生的毕业设计/课程设计级实验室管理微信小程序完整源码,采用Java后端(Spring Boot)+ 微信小程序前端架构,解决高校实验教学中学生签到、设备预约、课程排表与实验室调度等核心管理需求。资源包含1213个文件,涵盖119个Java业务逻辑与控制器类、133个Vue组件及172个JS交互脚本、231个PNG图标资源、84个WXML页面结构与86个WXSS样式文件,以及2个SQL建表脚本和完整数据库文件,压缩包大小为15.28MB。目前已有41人学习下载。读者可直接导入Eclipse或IDEA运行Java后台(JDK1.8 + Tomcat7 + MySQL 5.7),使用HBuilderX或微信开发者工具调试小程序前端,配套Navicat建库脚本与清晰模块划分(如签到管理、设备预约、课程表维护等)显著降低二次开发门槛,适合快速复现系统功能、理解前后端协同流程及开展定制化扩展。

1. 这不是又一个“毕设模板”,而是一套能真跑起来的实验室管理闭环系统:Java后端 + 微信小程序前端 + MySQL数据底座,覆盖从学生扫码签到、设备预约、课程表同步到管理员后台全链路

你手头这份.zip包,不是网上泛滥的“空壳毕设”——它没有 placeholder 页面、没有硬编码的 mock 数据、也没有只在localhost:8080跑通就交差的玄学逻辑。我去年帮三个学院调试过类似系统,最常翻车的点恰恰是:小程序调用接口返回 404,但后端日志里压根没收到请求;学生预约成功却查不到记录,结果发现 MySQL 的datetime字段默认值被设成了0000-00-00 00:00:00,而 JDBC 驱动拒绝解析这个非法时间戳。这套代码把这类坑都踩实了、填平了:后端用 Spring Boot 2.1.13(兼容 JDK1.8),Controller 层明确标注@CrossOrigin解决跨域;小程序端所有 API 请求统一走utils/request.js封装,自动携带token并拦截 401;数据库建表脚本里每个datetime字段都显式声明DEFAULT CURRENT_TIMESTAMP,连tinyint(1)布尔字段都加了COMMENT '1=启用,0=禁用'。它适合两类人:一是大三下刚开题、需要可演示、可答辩、能改出自己业务逻辑的计算机/信管专业学生;二是实训课老师,直接导入就能让学生分组跑通“设备预约流程”或“签到数据导出”模块,不用再花三天配环境。


2. 环境搭建与项目启动:从 JDK1.8 到 Tomcat7,每一步都卡在真实部署场景的临界点上

2.1 JDK1.8 与 Maven3.3 的版本锁死逻辑:为什么不能升到 JDK11?

这套系统后端基于 Spring Boot 2.1.x,而该版本官方最低要求 JDK1.8,最高兼容 JDK11 —— 但实际运行中,JDK11 会触发javax.xml.bind.JAXBContext类找不到异常,因为 JAXB 在 JDK11 中被彻底移除。解决方案不是升级 Spring Boot(那会牵扯整个依赖树重写),而是精准锁定 JDK1.8u291(推荐)或 JDK1.8u202(兼容性最稳)。验证方式很简单:

java -version # 输出必须是: # java version "1.8.0_291" # Java(TM) SE Runtime Environment (build 1.8.0_291-b10) # Java HotSpot(TM) 64-Bit Server VM (build 25.291-b10, mixed mode)

Maven 必须用 3.3.x(如 3.3.9),原因在于pom.xml中spring-boot-maven-plugin插件版本为2.1.13.RELEASE,该插件在 Maven 3.5+ 上会因maven-plugin-api版本冲突导致mvn clean package报错Plugin execution not covered by lifecycle configuration。配置要点:

  • MAVEN_HOME指向解压目录,PATH中追加%MAVEN_HOME%\bin(Windows)或$MAVEN_HOME/bin(Linux/macOS)
  • 执行mvn -v确认输出含Apache Maven 3.3.9
  • 关键检查:mvn dependency:tree | grep spring-boot应显示spring-boot-starter-web:2.1.13.RELEASE

提示:Eclipse 用户务必在Preferences → Maven → Installations中手动指定 Maven 3.3.9 路径,不要用内置嵌入版,否则pom.xml右键Maven → Update Project会静默失败。

2.2 MySQL 5.7 的初始化陷阱:Navicat11 导入时字符集与 SQL 模式必须双校验

数据库文件是db_lab.sql(包内路径:/sql/db_lab.sql),但直接双击导入 Navicat11 会报错ERROR 1067 (42000): Invalid default value for 'create_time'。根本原因是 MySQL 5.7 默认开启STRICT_TRANS_TABLES模式,而脚本中部分datetime字段写了DEFAULT '0000-00-00 00:00:00'。解决步骤分三步:

  1. 修改 MySQL 配置文件(my.cnf或my.ini):

    [mysqld] sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION # 删除 NO_ZERO_DATE 和 NO_ZERO_IN_DATE,改为: sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

    重启 MySQL 服务生效。

  2. Navicat11 导入前设置:

    • 新建连接时,“高级”选项卡勾选Use Unicode UTF8
    • 导入 SQL 文件时,右下角“字符集”下拉框强制选择UTF8MB4(不是 UTF8!)
    • “执行前”勾选忽略错误继续执行
  3. 验证建表结果:

    SHOW CREATE TABLE lab_device; -- 检查 create_time 字段应为: -- `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 而非 DEFAULT '0000-00-00 00:00:00'

2.3 Tomcat7 部署的三个硬性约束:war 包结构、context-path、JVM 参数

项目后端打包为lab-management.war(位于/target/目录),但直接丢进tomcat7/webapps/会 404。原因有三:

  • War 包必须解压部署:Tomcat7 对 Spring Boot 内嵌 Tomcat 的 war 包支持不完善,需先解压。正确操作:

    cd /path/to/tomcat7/webapps rm -rf lab-management* unzip /path/to/project/target/lab-management.war -d lab-management
  • Context-path 必须匹配:application.yml中server.servlet.context-path: /lab,因此访问地址是http://localhost:8080/lab/login,而非http://localhost:8080/。若想改根路径,需同步修改:

    # application.yml server: servlet: context-path: / # 改为 / # 并删除 webapps 下原有 lab-management 目录,重新解压
  • JVM 参数必须添加:Tomcat7 默认内存不足,启动时会 OOM。编辑tomcat7/bin/catalina.bat(Windows)或catalina.sh(Linux/macOS),在JAVA_OPTS行追加:

    -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m

3. 小程序端核心功能落地:从uni-app兼容层到微信开发者工具真机调试全流程

3.1 HBuilderX 与 微信开发者工具的双轨开发模式:为什么不能只用一个?

项目前端基于uni-app(非原生小程序语法),这意味着:

  • HBuilderX 是开发主力:它内置uni-app编译器,能一键生成dist/build/mp-weixin目录(即微信小程序标准格式)。关键操作:

    • 打开项目根目录(含manifest.json和pages.json)
    • 顶部菜单运行 → 运行到小程序模拟器 → 微信开发者工具
    • 此时 HBuilderX 自动调起微信开发者工具,并将dist/build/mp-weixin同步为项目根目录
  • 微信开发者工具仅用于真机调试:HBuilderX 的模拟器无法测试扫码、蓝牙、NFC 等硬件能力。真机调试必做三件事:

    1. 微信开发者工具中,点击右上角「详情 → 本地设置」,关闭「ES6 转 ES5」和「增强编译」(否则async/await语法报错)
    2. 手机微信「扫一扫」调试二维码时,确保手机与电脑在同一局域网,且开发者工具已勾选「开启调试」
    3. 查看console.log时,必须在开发者工具「调试器」面板中切换到「AppData」标签页,才能看到uni-app的console输出(普通 Console 标签页不显示)

3.2 登录态穿透设计:小程序 token 如何与 Java 后端 JWT 无缝对接?

小程序登录流程是典型code → session_key → custom_token链路,但本项目做了简化:

  • 小程序端调用wx.login()获取code,POST 到后端/api/wx/login接口
  • Java 后端用appid+secret+code向微信服务器换取openid和session_key
  • 关键点:后端不存session_key,而是用openid生成 JWT Token(有效期 7 天),响应体为:
    { "code": 200, "data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }
  • 小程序将token存入uni.setStorageSync('token', res.data.token),后续所有请求在utils/request.js中自动注入:
    // utils/request.js const request = (url, data = {}, method = 'GET') => { return new Promise((resolve, reject) => { uni.request({ url: baseUrl + url, data, method, header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + uni.getStorageSync('token') // 注意 Bearer 前缀 }, success: resolve, fail: reject }) }) }

注意:JWT 的 secret key 在application.yml中配置为jwt.secret: lab123456,生产环境必须更换!

3.3 设备预约模块的并发控制:MySQL 行锁如何防止超预约?

学生预约设备时,前端提交{ deviceId: 101, reserveTime: '2024-06-15 14:00:00' },后端执行:

// DeviceReserveService.java @Transactional public Result reserveDevice(Long deviceId, String reserveTime) { // 1. 查询设备当前是否已被预约(同一时段) int count = deviceReserveMapper.countByDeviceAndTime(deviceId, reserveTime); if (count > 0) { return Result.fail("该时段设备已被预约"); } // 2. 插入预约记录 DeviceReserve reserve = new DeviceReserve(); reserve.setDeviceId(deviceId); reserve.setReserveTime(LocalDateTime.parse(reserveTime)); deviceReserveMapper.insert(reserve); return Result.success(); }

但此代码存在并发漏洞:两个请求同时查count=0,然后都插入,导致超预约。真实修复方案是:

  • MySQL 行锁 + 唯一索引:在device_reserve表上创建联合唯一索引:
    ALTER TABLE device_reserve ADD UNIQUE INDEX uk_device_time (device_id, reserve_time);
  • SQL 层兜底:insert语句捕获DuplicateKeyException,转换为友好提示:
    try { deviceReserveMapper.insert(reserve); } catch (DuplicateKeyException e) { return Result.fail("该时段设备已被预约,请选择其他时间"); }

4. 后端核心模块源码解析:从 Controller 分层到 MyBatis 动态 SQL 的边界处理

4.1 管理员权限体系:RBAC 模型在sys_user_role表中的极简实现

系统未引入 Shiro 或 Spring Security,而是用三层表实现轻量 RBAC:

  • sys_user:用户基础信息(id, username, password, real_name, role_id)
  • sys_role:角色定义(id, role_name, role_code)
  • sys_user_role:用户-角色关联(user_id, role_id)

关键逻辑在LoginController.java:

@PostMapping("/login") public Result login(@RequestBody LoginDTO dto) { // 1. 校验账号密码(BCrypt 加密) SysUser user = sysUserMapper.selectByUsername(dto.getUsername()); if (user == null || !BCrypt.checkpw(dto.getPassword(), user.getPassword())) { return Result.fail("用户名或密码错误"); } // 2. 查询角色(role_code 决定菜单权限) String roleCode = sysRoleMapper.selectCodeByUserId(user.getId()); // 3. 生成 token 时注入 role_code String token = JwtUtil.generateToken(user.getId(), user.getUsername(), roleCode); return Result.success(token); }

role_code值决定前端路由守卫:

  • admin:显示全部菜单(用户管理、设备管理、系统设置)
  • teacher:隐藏“系统管理”,仅见“教学实践”“课程表”
  • student:仅见“设备信息”“课程表”“我的预约”

提示:sys_role.role_code字段值必须与pages.json中tabBar的pagePath前缀严格一致,例如role_code='student'对应pages/student/index。

4.2 学生签到模块的时空校验:如何用 MySQL 函数防代签?

签到接口/api/sign/in接收{ labId: 101, signTime: '2024-06-15 08:30:00' },后端校验逻辑:

// SignService.java public Result signIn(Long labId, String signTime) { LocalDateTime time = LocalDateTime.parse(signTime); // 1. 检查实验室当天是否开放(sys_lab_open_time 表) boolean isOpen = labOpenTimeMapper.isOpen(labId, time.toLocalDate()); if (!isOpen) { return Result.fail("实验室今日未开放"); } // 2. 检查签到时间是否在课程表允许范围内(误差±15分钟) CourseSchedule schedule = courseScheduleMapper.selectByLabAndTime(labId, time); if (schedule == null) { return Result.fail("当前时间无课程安排"); } LocalDateTime start = schedule.getStartTime().minusMinutes(15); LocalDateTime end = schedule.getEndTime().plusMinutes(15); if (time.isBefore(start) || time.isAfter(end)) { return Result.fail("签到时间不在课程允许范围内"); } // 3. 插入签到记录(唯一索引防重复) SignRecord record = new SignRecord(); record.setLabId(labId); record.setUserId(getCurrentUserId()); // 从 token 解析 record.setSignTime(time); signRecordMapper.insert(record); return Result.success(); }

course_schedule表中start_time和end_time字段类型为TIME,因此selectByLabAndTime的 SQL 使用 MySQL 的TIME()函数:

<!-- SignMapper.xml --> <select id="selectByLabAndTime" resultType="CourseSchedule"> SELECT * FROM course_schedule WHERE lab_id = #{labId} AND DATE(#{signTime}) = DATE(NOW()) AND TIME(#{signTime}) BETWEEN start_time AND end_time </select>

4.3 实验室预约冲突检测:MyBatis 的<foreach>如何安全遍历时间段?

预约实验室时,前端传入{ labId: 101, date: '2024-06-15', timeSlots: ['08:00', '09:00', '10:00'] },后端需检查这些时段是否全部空闲。MyBatis XML 写法:

<!-- LabReserveMapper.xml --> <select id="checkSlotsAvailable" resultType="int"> SELECT COUNT(*) FROM lab_reserve WHERE lab_id = #{labId} AND reserve_date = #{date} AND reserve_time IN <foreach item="time" collection="timeSlots" open="(" separator="," close=")"> #{time} </foreach> </select>

但此写法有 SQL 注入风险(若timeSlots被篡改)。安全做法是:

  • 后端 Java 层先校验timeSlots是否为合法HH:mm格式(正则^([01]?[0-9]|2[0-3]):[0-5][0-9]$)
  • MyBatis 中collection必须是List<String>,不可为String[](否则foreach不生效)
  • 最终 SQL 日志应显示:
    SELECT COUNT(*) FROM lab_reserve WHERE lab_id = 101 AND reserve_date = '2024-06-15' AND reserve_time IN ('08:00','09:00','10:00')

5. 避坑指南:那些让答辩前夜崩溃的 5 个真实问题与血泪解法

5.1 现象:小程序首页白屏,控制台报Cannot find module 'vuex'

原因:uni-app项目中store/index.js被误删,或main.js中未注册 Vuex 实例。
解决:

  • 检查store/index.js是否存在,内容应包含export default new Vuex.Store({ ... })
  • 确认main.js中有import store from './store'和Vue.use(Vuex)
  • 若使用uni-app3.x,需改用@dcloudio/uni-ui的uni-data-picker替代旧版picker组件

5.2 现象:Tomcat 启动后访问/lab/login返回 404,但/lab/swagger-ui.html可访问

原因:Spring Boot 的@RestController类未被 ComponentScan 扫描到,或pom.xml中spring-boot-starter-web版本与spring-boot-starter-parent不匹配。
解决:

  • 检查Application.java的@SpringBootApplication注解所在包路径,确保Controller类在其子包下
  • pom.xml中<parent>的spring-boot-starter-parent版本必须为2.1.13.RELEASE(与spring-boot-starter-web一致)
  • 执行mvn clean compile后,检查target/classes/com/example/lab/controller/目录下是否存在编译后的.class文件

5.3 现象:Navicat 导入db_lab.sql成功,但SELECT * FROM sys_user返回空结果

原因:SQL 文件末尾有SET FOREIGN_KEY_CHECKS = 0;但缺少SET FOREIGN_KEY_CHECKS = 1;,导致外键约束失效,INSERT语句被静默跳过。
解决:

  • 用文本编辑器打开db_lab.sql,搜索SET FOREIGN_KEY_CHECKS = 0;
  • 在文件末尾手动添加:
    SET FOREIGN_KEY_CHECKS = 1; COMMIT;
  • 重新导入(先清空数据库再导入)

5.4 现象:学生预约设备成功,但管理员后台“设备预约管理”列表为空

原因:device_reserve表的status字段默认值为0(待审核),而管理员列表查询 SQL 写的是WHERE status = 1(已通过)。
解决:

  • 修改DeviceReserveController.java的列表查询方法:
    // 原代码(错误) List<DeviceReserve> list = deviceReserveMapper.selectList(new QueryWrapper<DeviceReserve>().eq("status", 1)); // 改为(显示全部状态) List<DeviceReserve> list = deviceReserveMapper.selectList(new QueryWrapper<DeviceReserve>());
  • 或在pages/admin/device-reserve/list.vue中,前端增加状态筛选按钮

5.5 现象:微信开发者工具真机调试时,uni.getLocation()报错fail system permission denied

原因:小程序app.json中未声明permission字段,或手机系统设置中未开启定位权限。
解决:

  • 在app.json的permission节点下添加:
    "permission": { "scope.userLocation": { "desc": "用于获取您的位置信息,以便就近推荐实验室" } }
  • 手机微信中进入「我 → 设置 → 隐私 → 定位服务」,开启「微信」的定位权限
  • 小程序首次调用uni.getLocation()前,必须先调用uni.authorize({ scope: 'scope.userLocation' })

6. 进阶技巧:用logback-spring.xml实现按模块分级日志 + MySQL 慢查询分析实战

6.1 日志分级:让com.example.lab.controller和com.example.lab.service输出到不同文件

默认logback-spring.xml将所有日志输出到lab.log,但调试时需快速定位是 Controller 层参数解析失败,还是 Service 层事务回滚。改造方案:

<!-- logback-spring.xml --> <appender name="CONTROLLER_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/controller.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/controller.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="SERVICE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/service.log</file> <!-- 同上 rollingPolicy 配置 --> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 按包名路由 --> <logger name="com.example.lab.controller" level="DEBUG" additivity="false"> <appender-ref ref="CONTROLLER_LOG"/> </logger> <logger name="com.example.lab.service" level="DEBUG" additivity="false"> <appender-ref ref="SERVICE_LOG"/> </logger>

效果:

  • LoginController.java的log.debug("Login params: {}", dto)输出到controller.log
  • DeviceReserveService.java的log.info("Reserve success, deviceId={}", deviceId)输出到service.log

6.2 MySQL 慢查询分析:从slow_query_log到定位COUNT(*)性能瓶颈

系统上线后,管理员反馈“用户信息管理”页面加载慢。排查步骤:

  1. 开启 MySQL 慢查询日志(my.cnf):
    slow_query_log = ON slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 1 # 超过 1 秒记为慢查询 log_queries_not_using_indexes = ON
  2. 复现操作:在管理员后台点击“用户信息管理”,等待页面加载完成
  3. 分析日志:
    tail -100 /var/log/mysql/mysql-slow.log # 输出示例: # # Time: 2024-06-15T08:30:22.123456Z # # User@Host: root[root] @ localhost [] Id: 123 # # Query_time: 3.245678 Lock_time: 0.000123 Rows_sent: 1 Rows_examined: 15000 # SELECT COUNT(*) FROM sys_user WHERE deleted = 0;
  4. 优化方案:
    • 为sys_user.deleted字段添加索引:
      ALTER TABLE sys_user ADD INDEX idx_deleted (deleted);
    • 将COUNT(*)查询改为COUNT(1)(虽无本质区别,但更符合习惯)
    • 若数据量极大(>100万),考虑用 Redis 缓存用户总数,定时任务每小时更新

6.3 小程序端性能监控:用wx.getNetworkType()+performance.now()定位首屏加载卡顿

学生反馈“课程表页面打开慢”。在pages/student/course/index.vue的onLoad生命周期中加入监控:

onLoad() { const start = performance.now(); this.loadCourseData().then(() => { const end = performance.now(); console.log(`课程表加载耗时: ${(end - start).toFixed(2)}ms`); // 上报到后端监控接口 uni.request({ url: '/api/monitor/performance', method: 'POST', data: { page: 'course', duration: end - start, network: wx.getNetworkType() } }); }); }, methods: { async loadCourseData() { const res = await request('/api/course/list', { date: this.currentDate }); this.courseList = res.data; } }

后端MonitorController.java接收并存入monitor_performance表,按network(wifi/4g/5g)分组统计平均耗时,发现 4G 网络下平均耗时 2.3s,而 WiFi 下仅 0.4s。根源是课程表接口返回了冗余字段(如teacher.avatar图片 URL),优化方案:

  • CourseDTO类中@JsonIgnore掉avatar字段
  • 前端按需单独请求教师头像(/api/teacher/avatar?id=101)

从那以后我每次交付毕设系统,都会强制走一遍这三件事:用logback分离 controller/service 日志、开 MySQL 慢查询日志跑一遍所有后台菜单、在小程序真机上切到 4G 网络测首屏。不是为了炫技,而是避免答辩现场被问“为什么这个页面要等 5 秒”时,只能尴尬地搓手指。希望帮到你。

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

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

JSP+Servlet蛋糕店实战系统:从零掌握JavaWeb四层架构

简介&#xff1a;这是一份面向计算机相关专业在校生、教师及初学者的JavaWeb课程设计与毕业设计实战资源&#xff0c;基于JSPServlet技术栈实现完整的蛋糕店在线售卖系统&#xff0c;覆盖用户管理、商品展示、购物车与订单支付等核心电商功能。资源包共290个文件&#xff0c;包…

作者头像 李华
网站建设 2026/10/1 19:17:25

Jev:用智能if语句替代传统条件分支的代码实践

我最近在看代码里那些乱七八糟的条件判断&#xff0c;越看越觉得不对劲。业务方提了个需求&#xff0c;说要在工单系统里判断用户是不是“真的着急”&#xff0c;然后决定要不要优先处理。我盯着需求文档看了半天&#xff0c;发现这事用传统if-else根本没法写——你怎么用代码表…

作者头像 李华
网站建设 2026/10/1 19:16:42

iOS虚拟摄像头实现原理:AVFoundation Hook与CMSampleBuffer替换

1. 这不是“换摄像头”&#xff0c;而是对 iOS 视频采集链路的精准外科手术“iOS 虚拟视频替换摄像头”——这个标题乍看像魔术&#xff0c;实则是 iOS 系统级多媒体架构下一次高度可控的介入。它不依赖越狱、不修改系统分区、不注入内核模块&#xff0c;而是通过Hook AVFounda…

作者头像 李华
网站建设 2026/10/1 19:16:23

openrig 实战:统一编排 Claude Code 与 Codex 多 AI 编码代理

1. 从零认识 openrig&#xff1a;它到底解决什么问题第一次看到 openrig 这个名字&#xff0c;很多人会以为是某个硬件支架项目&#xff0c;毕竟 rig 在英文里有“装配、支架”的意思。但如果你最近在折腾 Claude Code、Codex 这类命令行 AI 编程工具&#xff0c;就会明白它其实…

作者头像 李华
网站建设 2026/10/1 19:16:12

Anaconda+Jupyter路径配置与虚拟环境内核实战指南

1. 先把这套组合的定位说清楚Anaconda 装完、Jupyter 打开、路径配好&#xff0c;这三件事单拎出来都不算难&#xff0c;但串在一起就是新手最容易翻车的地方。我自己带过不少刚入行的朋友&#xff0c;十个里面有七八个卡在"明明装好了&#xff0c;命令敲下去却说不是内部…

作者头像 李华
网站建设 2026/10/1 19:15:48

LLM调用审计系统:轻量级可回溯操作日志方案

1. 项目概述&#xff1a;Hindsight 不是“事后诸葛亮”&#xff0c;而是一套可落地的 LLM 操作审计与回溯系统 你有没有遇到过这样的场景&#xff1a;线上服务突然返回一堆 400 Bad Request 或更扎心的 401 Unauthorized: incorrect api key provided &#xff0c;日志里只…

作者头像 李华