SSM+Flask双引擎架构:宠物医院信息管理系统开发实践
1. 项目从0到1为什么我坚持用SSMFlask做双引擎宠物医院信息管理系统说直白点就是给宠物诊所做的一套业务中台前台要挂号、预约、办会员诊室要开病历、写处方、做检查记录药房要管库存、划价、发药老板还要看每天的营收流水和热门服务排行。这些环节如果全靠Excel表格和微信群对接等到宠物数量超过几百只的时候整个诊所的运营就会乱成一锅粥。我做这个项目时最核心的考量不是“技术越新越好”而是“怎么在有限的人力下把业务闭环跑通”。项目最终采用了 Java SSMSpring SpringMVC MyBatis作为主后端框架Python Flask 作为辅助服务两块服务通过 HTTP 接口协同工作。这套组合最初看起来有点“混搭”但实际跑下来我可以说这是目前毕业设计、中小型商用系统里性价比极高的一套方案。1.1 宠物医院管理系统的核心业务闭环我们先捋一遍一个真实的宠物医院每天会发生什么宠物主进门前台先建档宠物信息、主人信息、疫苗情况然后根据症状分诊安排医生接诊。医生问诊后开检查单或者直接开药检查结果出来以后写电子病历顺便把处方单打出来。主人去药房缴费取药如果是需要住院观察的宠物还要办理住院登记、每日巡查记录、出院结算。这一整套流程落到管理系统里就是六大核心模块宠物与主人档案管理建档、宠物照片、疫苗记录、过敏史预约与挂号管理线上预约、现场挂号、号源管理、排队叫号门诊诊疗管理电子病历、检查检验记录、诊断结果、处方开立药房与库存管理药品信息、入库、出库、库存预警、效期管理收费与结算管理处方划价、收费记录、退费处理、营收统计住院与护理管理住院登记、护理记录、体温体重跟踪、出院结算这六个模块并不是孤立的它们之间有很强的数据流转关系。比如“处方开立”会联动“药房库存扣减”和“收费结算金额生成”“挂号完成”才能在医生端看到患者列表“检查报告回填”才能把完整病历归档。所以设计系统时数据库的事务边界和模块间的调用关系比单张表怎么建更重要。1.2 为什么是SSMFlask而不是Spring Boot全家桶很多同学看到这个技术选型会问直接上 Spring Boot JPA 或者 MyBatis-Plus 一套搞定不行吗非要把 Python 拉进来搞个“混合双打”我当初定这个架构有三点实际考虑。第一SSM 是 Java 后端最经典的组合在学校课程和企业老项目里存量巨大。Spring 负责 Bean 管理和事务控制SpringMVC 负责接口路由和参数绑定MyBatis 负责 SQL 映射。这套组合对“业务逻辑重、报表统计多、权限模型复杂”的管理系统非常友好尤其是 MyBatis 手写 SQL 的能力在关联查询频繁的诊疗收费场景里比 JPA 自动生成 SQL 要好调教得多。第二Flask 在项目里承担的不是主业务而是“轻量辅助服务”。比如生成 PDF 版病历报告、调用图片识别接口识别药品包装、跑定时任务做数据统计并推送给管理员这些活儿交给 Python 生态做效率比 Java 手写要高一个量级。Flask 本身足够轻一个文件就能起服务非常适合作为辅助引擎存在。第三也是最现实的——项目交付物要包含“源码 LW论文 调试文档 讲解”既然是教学和演示向的项目双语言架构本身就是加分项。它能同时展示 Java 和 Python 两套技术栈的整合能力这在答辩和演示时是很实在的亮点。注意SSM 和 Flask 的整合不是简单的“两个程序各跑各的”而是要有明确的职责边界。我的划分方式是所有涉及事务性写操作和核心业务查询的接口全部走 SSM所有涉及外部服务调用、定时任务、复杂数据处理的任务走 Flask。这个边界一定不能模糊否则后期维护就是灾难。2. 数据模型与核心表结构设计先想清楚整个系统有哪些数据再来谈建表。我设计数据库的原则是“流程驱动表跟随业务走”。也就是说数据库不是一开始就画一堆表而是先画出业务流程图然后在每个流程节点上识别出需要持久化的数据再归纳成表。2.1 围绕业务流程的八张核心表这里我挑几张最核心的表展开说这些表基本覆盖了宠物医院 80% 的业务。宠物主人表owner字段包括 owner_id主键、name、phone、address、wechat_openid用于小程序登录绑定、create_time。手机号和 openid 都做唯一索引。因为一个主人可能带多只宠物来就诊所以主人表是独立的不要和宠物表混在一起。宠物档案表petpet_id 主键、owner_id 外键、pet_name、pet_type猫/狗/异宠、breed、gender、birthday、weight、sterilized是否绝育、vaccine_record疫苗记录用 JSON 或文本字段存储、photo_url。这里要注意宠物和主人是“多对一”关系一只宠物只属于一个主人但一个主人可以有多只宠物。预约挂号表appointmentappointment_id、pet_id、owner_id、doctor_id、appointment_date、time_slot上午/下午/晚间、status待接诊/已就诊/已取消/已过号、create_time。设计这张表时必须加一个唯一约束doctor_id, appointment_date, time_slot避免同一个医生在同一时间段被重复预约。这个唯一约束我在前两版里漏掉了结果测试时同一个医生同一个上午被约了三次后来才加上。门诊病历表medical_recordrecord_id、pet_id、appointment_id、doctor_id、symptom主诉症状、diagnosis诊断结果、treatment_plan治疗方案、check_results检查结果可以存 JSON 数组、create_time。病历表是整个系统里数据量增长最快的表建议按月份做分区或者至少建一个 create_time 索引不然三个月后查询就会明显变慢。处方表prescription和处方明细表prescription_item处方表记录一次开药的总体信息主键 prescription_id、record_id、total_amount、status未缴费/已缴费/已发药。处方明细表记录每一种药品的开立信息主键 item_id、prescription_id、drug_id、quantity、unit_price、subtotal外键指向药品表。把处方头和明细分开是为了支持“一张处方包含多种药品”的天然业务结构。药品库存表drugdrug_id、drug_name、specification规格、manufacturer生产厂家、stock_quantity、safety_stock安全库存阈值、purchase_price、sale_price、expiry_date。每次开药发货时库存扣减必须放在事务里执行并且要先判断 stock_quantity 是否充足否则会出现超卖。收费记录表paymentpayment_id、prescription_id、amount、payment_method现金/微信/支付宝/刷卡、operator_id操作人、payment_time。这张表是营收统计的数据来源建议把 amount 字段同时冗余存一份到处方表里统计时直接用处方表的金额字段少一次关联查询。2.2 实体类先行我如何用Java实体快速生成建表SQL建表之前我先把 Java 实体类写好然后利用 MyBatis-Plus 的代码生成器根据实体类自动生成建表 SQL 语句。这样做有两个好处一是实体类和表结构保证字段一一对应不会出现代码里写了 getter 但数据库没这个列的情况二是通过实体类上的注解比如TableName、TableField可以自动推导出表的字段名、类型、长度、是否为 null生成 DDL 时不用手动一个个去敲。举个实际的例子宠物档案表的实体类设计大概是这样的Data TableName(pet) public class Pet { TableId(type IdType.AUTO) private Long petId; TableField(value owner_id, notNull true) private Long ownerId; TableField(value pet_name, length 50, notNull true) private String petName; TableField(value pet_type, length 20) private String petType; TableField(value breed, length 50) private String breed; TableField(value birthday, fieldType DATE) private LocalDate birthday; TableField(value weight, fieldType DECIMAL(5,2)) private BigDecimal weight; TableField(value sterilized, fieldType TINYINT(1)) private Boolean sterilized; TableField(value vaccine_record, fieldType JSON) private String vaccineRecord; }有了实体类框架会自动生成对应的建表语句我再根据实际的索引需求做手动微调比如在 owner_id 上补一个索引。这个过程比我早期纯手工写 SQL 再对着实体类逐字段核对要高效得多基本不会出现字段长短不一、类型对不上的低级问题。建议字段命名统一用下划线风格owner_idJava 实体类里用驼峰ownerIdMyBatis-Plus 默认开启驼峰映射完全对得上。如果你在实体类里乱用缩写比如 ownerId 写成 owid后面所有业务代码的可读性都会直线下降。3. 核心功能实现预约、就诊、库存三大主链路系统功能虽然多但真正的“主链路”只有三条预约、就诊、库存。这三条链路跑顺了整个系统就已经能用了。我分别拆解三条链路的实现思路和关键代码段。3.1 预约挂号模块Controller和Service怎么拆才不乱预约挂号的业务逻辑并不复杂但最容易写乱。我第一次写的时候把所有逻辑都堆在 Controller 里一个方法三百行后来加需求时根本不敢动。重构之后我严格遵循“Controller 只做路由和参数校验Service 做业务处理Mapper 做数据访问”的分层原则。到了预约挂号这一步核心的 Service 方法长这样Service public class AppointmentServiceImpl implements AppointmentService { Autowired private AppointmentMapper appointmentMapper; Autowired private PetMapper petMapper; Override Transactional(rollbackFor Exception.class) public Appointment createAppointment(AppointmentCreateDTO dto) { // 1. 校验宠物是否属于当前预约人 Pet pet petMapper.selectById(dto.getPetId()); if (pet null || !pet.getOwnerId().equals(dto.getOwnerId())) { throw new BusinessException(宠物信息校验失败); } // 2. 校验号源通过唯一约束兜底这里做二次校验 AppointmentQuery query new AppointmentQuery(); query.setDoctorId(dto.getDoctorId()); query.setAppointmentDate(dto.getAppointmentDate()); query.setTimeSlot(dto.getTimeSlot()); long count appointmentMapper.selectCount(query); if (count 0) { throw new BusinessException(该时段已被预约请选择其他时间段); } // 3. 创建预约记录默认状态为 PENDING待就诊 Appointment appointment new Appointment(); BeanUtils.copyProperties(dto, appointment); appointment.setStatus(AppointmentStatus.PENDING); appointmentMapper.insert(appointment); return appointment; } }这里有两个关键设计值得说明。一是事务边界createAppointment方法上加了Transactional因为“校验号源 插入预约记录”必须是一个原子操作。如果中间抛了异常但没事务就可能出现“校验通过了但没插入成功”或者“插入成功了但校验没走”的脏数据。二是状态机预约状态我用了枚举而不是自由字符串避免出现“待就诊”和“待見诊”这种人工拼写错误。3.2 跨语言调用Java如何优雅地调用Flask接口整个项目最需要耐心的部分就是跨语言调用。我举一个实际的功能场景宠物主人在小程序端上传宠物疫苗本的照片系统自动识别疫苗种类和接种日期并把结构化数据存储到档案里。Java 端负责接收图片、调用 Flask 服务、解析返回结果、落库存储。整个调用链路由三块组成第一步Java 端用 RestTemplate或 HttpClient发起 POST 请求把图片以 MultipartFile 的形式传给 Flask 服务public VaccineInfo parseVaccineImage(MultipartFile file) { // 构造要传给Flask的请求数据 HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); // 用LinkedMultiValueMap封装表单数据 LinkedMultiValueMapString, Object body new LinkedMultiValueMap(); body.add(file, new ByteArrayResource(file.getBytes()) { Override public String getFilename() { return file.getOriginalFilename(); } }); HttpEntityLinkedMultiValueMapString, Object requestEntity new HttpEntity(body, headers); // 设置超时时间避免Flask服务异常时Java端无限等待 SimpleClientHttpRequestFactory factory new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(3000); factory.setReadTimeout(10000); RestTemplate restTemplate new RestTemplate(factory); // 调用Flask接口并接收JSON结果 String url http://localhost:5000/api/vaccine/parse; ResponseEntityVaccineParseResponse response restTemplate.postForEntity(url, requestEntity, VaccineParseResponse.class); if (response.getStatusCode().is2xxSuccessful()) { return response.getBody().getData(); } else { throw new BusinessException(疫苗识别服务异常); } }第二步Flask 端提供一个/api/vaccine/parse接口接收图片后交给 OCR 模型做文字识别再把结果包装成统一的 JSON 结构返回from flask import Flask, request, jsonify import ocr_service app Flask(__name__) app.route(/api/vaccine/parse, methods[POST]) def parse_vaccine(): file request.files.get(file) if file is None: return jsonify({code: 400, msg: 未接收到图片, data: None}), 400 # 调用OCR识别服务 result ocr_service.parse_vaccine_card(file) # 统一返回结构code msg data return jsonify({code: 0, msg: success, data: result})第三步也是最容易忽略的统一返回结构。Java 和 Flask 两端必须约定同一个 JSON 格式我统一用的是{code: 0, msg: success, data: {...}}code 为 0 表示成功非 0 是业务侧的错误码。这个约定一定要写在接口文档的最开头因为一旦两端团队各自发挥后面联调时字段对不上排查问题的成本极高。经验之谈跨语言服务的边界上最怕出现“Java 把异常吞掉但没记日志”的情况。我在调用 Flask 的代码里加了一个全局异常处理器凡是 RestTemplate 调用失败或者返回非 2xx 响应都会把 URL、请求参数、响应体完整打出来。否则你根本不知道到底是 Flask 挂了、参数传错了还是响应解析失败。3.3 就诊病历与处方收费事务这样设计才不出错就诊环节最核心的操作是“医生提交病历 开出处方 药房扣库存 收费生成账单”。这四个操作在业务上是连续的但在数据库层面必须保证一致性要么全部成功要么全部不成功。这里我用了二级事务模型。SSM 主服务负责业务事务管理病历和处方药品库存扣减通过 MQ 或同步调用执行。由于宠物医院系统并发量不高我选择同步调用不引入消息中间件除非未来要对接连锁药房。核心代码如下Transactional(rollbackFor Exception.class) public void submitDiagnosis(DiagnosisSubmitDTO dto) { // 1. 写入病历主表 MedicalRecord record new MedicalRecord(); BeanUtils.copyProperties(dto, record); medicalRecordMapper.insert(record); // 2. 写入处方主表 Prescription prescription new Prescription(); prescription.setRecordId(record.getRecordId()); prescription.setStatus(PrescriptionStatus.UNPAID); prescriptionMapper.insert(prescription); // 3. 循环写入处方明细并同时扣减库存 ListPrescriptionItemDTO items dto.getItems(); for (PrescriptionItemDTO item : items) { Drug drug drugMapper.selectById(item.getDrugId()); if (drug null) { throw new BusinessException(药品不存在药品ID: item.getDrugId()); } if (drug.getStockQuantity() item.getQuantity()) { throw new BusinessException(库存不足: drug.getDrugName()); } // 扣减库存注意这里是 update 语句而不是先 select 再 update int rows drugMapper.deductStock(item.getDrugId(), item.getQuantity()); if (rows 0) { throw new BusinessException(库存扣减失败请刷新后重试); } // 写入处方明细 PrescriptionItem prescriptionItem new PrescriptionItem(); prescriptionItem.setPrescriptionId(prescription.getPrescriptionId()); prescriptionItem.setDrugId(item.getDrugId()); prescriptionItem.setQuantity(item.getQuantity()); prescriptionItem.setUnitPrice(drug.getSalePrice()); prescriptionItem.setSubtotal(drug.getSalePrice().multiply( new BigDecimal(item.getQuantity()))); prescriptionItemMapper.insert(prescriptionItem); } // 4. 生成收费记录 Payment payment new Payment(); payment.setPrescriptionId(prescription.getPrescriptionId()); payment.setAmount(prescription.getTotalAmount()); payment.setPaymentStatus(PaymentStatus.PENDING); paymentMapper.insert(payment); }这里我专门用了“更新后返回受影响行数”的写法而不是“先查询库存再更新”因为在高并发下先查后改会出现超卖。虽然宠物医院不太可能瞬时高并发但写代码时保持这种“安全习惯”是值得的。受影响行数为 0 时直接抛异常让事务回滚这样不会出现库存负数。4. 小程序/前端对接与API设计如果说后端是大脑API 设计就是神经和血管。整套系统最终会有两个客户端一个是 Web 管理端给前台、医生、药房、老板用另一个是微信小程序端给宠物主人用。所以 API 在设计之初就要兼顾两端。4.1 给微信小程序预留的登录态与Token体系小程序端和 Web 端的认证方式完全不同。Web 端我用的是传统的 Session 登录浏览器自动维护 Cookie小程序不支持 Cookie所以必须用 Token。我的方案是小程序里调用wx.login()获取临时 code然后传给后端后端调用微信的 code2session 接口换取 openid再生成一个自定义 TokenUUID 或 JWT返回给小程序。后续请求时小程序在 Header 里带上Authorization: Bearer token后端用一个拦截器统一校验。核心的拦截器逻辑是这样的public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行OPTIONS预检请求 if (OPTIONS.equals(request.getMethod())) { return true; } String token request.getHeader(Authorization); if (StringUtils.hasText(token) token.startsWith(Bearer )) { token token.substring(7); Long userId tokenRedisService.getUserId(token); if (userId ! null) { request.setAttribute(currentUserId, userId); return true; } } response.setStatus(401); response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:401,\msg\:\请先登录\}); return false; } }我把 Token 存放在 Redis 里而不是 JWT主要是考虑可以随时吊销 Token比如用户主动退出登录或管理员封禁账号比 JWT 的“签发后不可控”更便于管理。4.2 统一响应格式与接口文档管理系统 API 全部采用统一的响应格式字段类型说明codeint0 表示成功非 0 表示业务错误码如 400、401、500msgstring提示信息直接展示给用户或前端弹窗dataobject/array业务数据成功时返回具体数据失败时可为 null比如获取宠物列表的响应是{ code: 0, msg: success, data: [ { petId: 1, petName: 豆豆, petType: 狗, breed: 柯基, weight: 12.5 } ] }接口文档我用 Apifox 管理每个接口标注好请求方式、请求参数类型、响应示例。这套文档是前后端联调的唯一依据谁改谁同步更新文档否则另一方全凭猜项目肯定会延期。提醒文档里一定要标好“哪些接口需要登录才能访问”。我踩过一个坑健康档案接口忘了加鉴权结果小程序端未登录状态也能直接查到任意宠物档案虽然只是测试环境但这个普及教训让我从此把所有接口默认加上“必须登录”需要匿名访问的再单独白名单放行。5. 常见问题排查与避坑实录跑了几个月的测试环境最折磨人的永远是那些不上不下、不好复现的奇怪问题。我挑几个有代表性的写出来给大家做个参考。5.1 跨语言调用的三大坑第一个坑Flask 返回的 JSON 里字段是nullJava 端反序列化直接报HttpMessageNotReadableException。这个问题是因为 Java 端的 DTO 里用了BigDecimal而 Flask 返回的null在 JSON 里对应null如果实体类字段类型是基本类型BigDecimal而不是包装类型就会失败。解决方案是实体类统一用包装类型不接受基本类型。第二个坑Flask 服务拿到图片后处理耗时超过 10 秒Java 端 RestTemplate 默认的 readTimeout 是 30 秒但如果有人把超时改小了就会出现“Java 端报错Flask 端其实已经处理完并入库”的情况。这个问题本质上是重复提交幂等性问题我的方案是每次调用都带上一个 requestIdFlask 处理完把结果缓存起来并返回Java 端如果超时重试Flask 直接返回缓存结果保证不会重复识别和重复入库。第三个坑两个服务的字符集不一致。Flask 如果返回的 JSON 里直接含中文字符但响应头没有声明charsetutf-8Java 端解析时会把中文变成问号。解决方法是 Flask 端显式设置响应头的 Content-Type 为application/json; charsetutf-8Java 端 RestTemplate 也设置 UTF-8 编码。5.2 数据库中文乱码与连接池耗尽中文乱码是最常见也最烦人的低级错误。我们做了几件事MySQL 连接串加characterEncodingutf8建表时指定DEFAULT CHARSETutf8mb4Spring 端统一设置server.servlet.encoding。如果这三步都做了还有乱码大概率是数据库本身已经是 latin1 的旧表只能重建表或者用ALTER TABLE转换。连接池耗尽问题在高并发场景容易出现。HikariCP 默认最大连接数是 10如果代码里有慢查询或者连接泄漏比如 finally 里忘了关闭 ResultSet连接池很快就满了。排查方法是打开 HikariCP 的 leakDetectionThreshold 参数设置为 6000060 秒超过这个时间未归还的连接会在日志里打印堆栈信息直接定位泄漏点。5.3 部署时的Java环境与端口问题有些同学的开发机装了好几个 JDK 版本环境变量 PATH 指向的可能是旧版本。我建议在部署文档里把JAVA_HOME的路径写死到具体版本目录并且在启动脚本里显式指定使用哪个 Java 可执行文件不要依赖系统 PATH。端口问题则是典型的“复用冲突”尤其是 8080 端口经常被乱七八糟的程序占用用netstat -ano | findstr 8080查一下是谁占的不行就直接改端口。6. 打包部署从开发机到服务器的完整流程开发完成之后部署上线是另一道坎。我在这里直接写一份我实际用来部署的流程环境是 CentOS 7 Tomcat 8.5 MySQL 5.7 Python 3.8读者可以根据自己服务器环境微调。6.1 Java端打包如果是 SSM 工程我习惯打成 WAR 包部署到 Tomcat。项目里配置好 Maven 的pom.xml后在项目根目录执行mvn clean package -DskipTests打包完成后target目录下会生成一个pet-hospital.war把这个文件上传到服务器的 Tomcatwebapps目录下重启 Tomcat 后访问http://服务器IP:8080/pet-hospital/就能看到系统入口。但我在实际部署中强烈建议用 Spring Boot 的方式改造一下——即便原来是 SSM也可以在保留 SSM 代码结构的基础上加一个 Spring Boot 的启动类直接打成可执行 JAR 包。这样部署时只需要java -jar pet-hospital.jar --spring.profiles.activeprod不用再装 Tomcat运维成本低了很多。我有一个版本就是这么干的省掉了在服务器上配置 Tomcat 的麻烦。6.2 Flask端部署Flask 端不能用自带的app.run()直接跑生产尽管开发时很方便但生产环境性能和安全都跟不上。我用 Gunicorn 部署生产启动命令是gunicorn -w 4 -b 0.0.0.0:5000 app:app-w 4表示启动 4 个 worker 进程-b指定监听 IP 和端口。为了不让 Flask 服务因为终端关闭而退出用 supervisor 守护进程托管配置里加 restart 参数崩溃后自动拉起。6.3 Nginx反向代理服务器上加 Nginx把 80 端口的请求按路径分发/api/java/前缀的转发到 Tomcat/JAR 端口比如 8080/api/python/前缀的转发到 Gunicorn 的 5000 端口。这样做的好处是前端只面向一个域名不会遇到跨域问题同时 Nginx 可以做静态资源缓存和请求日志记录。server { listen 80; server_name pet.example.com; # Java后端接口 location /api/java/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # Flask辅助服务接口 location /api/python/ { proxy_pass http://127.0.0.1:5000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这套配置跑起来后前端页面Web 管理端直接访问http://pet.example.com/index.html小程序请求的 baseURL 也统一写http://pet.example.com/api/java不用再区分两个服务的真实地址清爽很多。我实际部署过程中踩的一个小坑是 Nginx 的 proxy_pass 末尾是否带/带不带直接影响路径的转发方式。比如proxy_pass http://127.0.0.1:8080/;会把/api/java/appointment/list转发成/appointment/list前缀被替换掉不带/时会保留完整路径。这个规则不试错几次真的容易记混。最后再分享一点个人体会做这种“双框架混合架构”的系统最难的不是技术而是“边界意识”。Java 和 Flask 各自管好自己的领域通信靠接口数据靠约定千万不要在 Java 里硬写 Python 风格的代码也不要在 Flask 里尝试做 Java 的主业务。只要边界清晰这套系统不但能用于毕业设计也完全能承接一家中小型宠物诊所的真实业务流程。如果你正在做类似的系统我建议先把预约、就诊、库存三条链路跑通再加入报表、提醒这类锦上添花的功能你会发现整个项目的复杂度是可控的。

相关新闻

实战验证——把 SDK 塞进一个 macOS 原生 Agent 应用:TaoToken 统一 Key 通道接入 SwiftUI + MCP 全流程

实战验证——把 SDK 塞进一个 macOS 原生 Agent 应用:TaoToken 统一 Key 通道接入 SwiftUI + MCP 全流程

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

2026/10/9 16:11:20 阅读更多 →
1000 万小时视频开源、770B 压到 200GiB:TaoToken 视角下的 AI 大小模型双轨部署

1000 万小时视频开源、770B 压到 200GiB:TaoToken 视角下的 AI 大小模型双轨部署

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

2026/10/9 16:11:20 阅读更多 →
开源互联网医院系统拆解:挂号、问诊、处方与支付全流程

开源互联网医院系统拆解:挂号、问诊、处方与支付全流程

去年接了一个互联网医院预研的评估单,老板让我先找开源项目做技术摸底。我翻遍几个主流代码托管平台,发现一个挺有意思的现象:搜索“互联网医院”出来的仓库不少,但点进去要么只有一张患者端的UI空壳,要么后台躺着几十…

2026/10/9 16:11:20 阅读更多 →

最新新闻

Func、Skill 与 MCP:Agent 工具调用三层架构实战指南

Func、Skill 与 MCP:Agent 工具调用三层架构实战指南

最近在折腾 Agent 开发时,被一个概念问题搞得有点上头:工具到底该用 func、skill 还是 MCP?搜索引擎的结果五花八门,有说 skill 是未来,有说 MCP 才是标准,还有的直接把 function calling 当成全部。等我把…

2026/10/9 17:18:14 阅读更多 →
Android HTML答题引擎:Kotlin+Java双语言深度集成方案

Android HTML答题引擎:Kotlin+Java双语言深度集成方案

简介:这是一份面向Android开发初学者与进阶学习者的HTML整合型答题APP完整源码项目,适用于移动应用开发实践、混合式界面设计及Kotlin/Java协同开发场景。资源共786个文件,总大小47.87MB,涵盖182个Java与8个Kotlin源文件&#xff…

2026/10/9 17:18:14 阅读更多 →
手写BP神经网络实现鸢尾花和红酒分类:从原理到避坑

手写BP神经网络实现鸢尾花和红酒分类:从原理到避坑

简介:这是一份面向高校机器学习课程的BP神经网络实验资源,以鸢尾花与红酒数据集为对象,完成二分类/多分类建模练习,适合正在学习前馈神经网络、反向传播算法或需要快速搭建课程实验的学生参考。压缩包共收录18个文件,包…

2026/10/9 17:18:14 阅读更多 →
Ubuntu下zip压缩解压指南:命令行操作、乱码解决与tar.gz选型

Ubuntu下zip压缩解压指南:命令行操作、乱码解决与tar.gz选型

我最近在整理一批旧项目的归档文件,同事从Windows那边发过来的压缩包在Ubuntu下面解压时又是一堆乱码文件名,加上自己这边要批量打包日志目录上传,来来回回折腾了好几次。索性把在Ubuntu下用zip压缩和解压文件夹的完整操作、踩坑记录和替代方…

2026/10/9 17:18:14 阅读更多 →
MySQL新手避坑指南:从命令行实操到生产级排错

MySQL新手避坑指南:从命令行实操到生产级排错

简介:本资源是一份面向数据库初学者与Web开发入门者的MySQL基础教学课件,聚焦关系型数据库核心概念、设计方法与SQL实践,特别适合高校计算机课程教学、自学备考及后端开发岗新人夯实基础。课件以PPTX格式呈现,共1个文件&#xff0…

2026/10/9 17:18:13 阅读更多 →
抽象工厂与原型模式对比:从产品族到对象复制的创建型模式选型指南

抽象工厂与原型模式对比:从产品族到对象复制的创建型模式选型指南

说实话,我最早把抽象工厂和原型模式放在一起对比,并不是因为它俩长得像,恰恰相反,它俩一个是"批量生产新对象",一个是"复制已有对象",从设计思路上八竿子打不着。但最近在给几个做技术…

2026/10/9 17:17:10 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练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/9 6:17:20 阅读更多 →