java实现医院门诊排班与预约系统【代码】
文章目录
- 前言
- 一、遇到的问题
- 二、实现过程
- 1.数据库设计
- 2.实体类
- 3.医生添加排班或修改排班方法
- 4.患者预约方法
- 5.患者修改预约
- 6.患者取消预约
前言
该文章从实际需求出发,实现医生设置自身排班与患者预约功能。
一、遇到的问题
1、医生设置的排班表不能有时间上的冲突。
2、医生修改自己的排班时不能与数据库中的数据冲突。
3、如果多为患者同时预约需要使用redis做支撑解决并发问题。
二、实现过程
1.数据库设计
可根据实际需求添加或删除字段
排班数据库 rqri_guidance_time
| 字段名 | 字段类型 | 长度 | 注释 |
|---|---|---|---|
| guidance_time_id | int | 11 | 排班ID |
| date | date | 日期 | |
| starttime | time | 开始时间点 | |
| endtime | time | 结束时间点 | |
| num | int | 2 | 可预约次数 |
| residue | int | 2 | 剩余可预约次数 |
| doctor_id | int | 11 | 医生ID |
预约详情表 rqri_guidance_time_relation
| 字段名 | 字段类型 | 长度 | 注释 |
|---|---|---|---|
| reservation_id | int | 11 | 预约关系ID |
| guidance_time_id | int | 11 | 排班ID |
| patient_id | int | 11 | 患者ID |
| remarks | text | 病情描述 | |
| file_id | varchar | 256 | 附件ID |
| reservation_type | int | 11 | 预约类型ID |
| doctor_id | int | 11 | 医生ID |
| reply | text | 回复 | |
| reply_files_id | varchar | 256 | 回复附件ID |
| status | int | 1 | 状态ID |
| isfinish | int | 1 | 是否已完成咨询 |
| finish_time | datetime | 完成咨询的时间 | |
| create_time | datetime | 创建时间 |
2.实体类
@Table(name = "rqri_guidance_time")
@Data
public class RqriGuidanceTime implements Serializable {/*** 医生可预约时间id*/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@ApiModelProperty(value = "医生可预约时间id", required = false, dataType = "Integer")@Column(name = "guidance_time_id")private Integer guidanceTimeId;/*** 日期*/@ApiModelProperty(value = "日期", required = true, dataType = "Date")@Column(name = "date")@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")private Date date;/*** 开始时间点*/@ApiModelProperty(value = "开始时间点", required = true, dataType = "Date")@Column(name = "starttime")@JsonFormat(locale="zh", timezone="GMT+8", pattern="HH:mm")private Date starttime;/*** 结束时间点*/@ApiModelProperty(value = "结束时间点", required = true, dataType = "Date")@Column(name = "endtime")@JsonFormat(locale="zh", timezone="GMT+8", pattern="HH:mm")private Date endtime;/*** 可预约次数*/@ApiModelProperty(value = "可预约次数", required = true, dataType = "Integer")@Column(name = "num")private Integer num;/*** 剩余可预约次数*/@ApiModelProperty(value = "剩余可预约次数", required = true, dataType = "Integer")@Column(name = "residue")private Integer residue;/*** 医生id*/@ApiModelProperty(value = "医生id", required = true, dataType = "Integer")@Column(name = "doctor_id")private Integer doctorId;
@Table(name = "rqri_guidance_time_relation")
@Data
public class RqriGuidanceTimeRelation implements Serializable {/*** 预约关系id*/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@ApiModelProperty(value = "预约关系id", required = false, dataType = "Integer")@Column(name = "reservation_id")private Integer reservationId;/*** 预约时段id*/@ApiModelProperty(value = "预约时段id", required = true, dataType = "Integer")@Column(name = "guidance_time_id")private Integer guidanceTimeId;/*** 患者id*/@ApiModelProperty(value = "患者id", required = true, dataType = "Integer")@Column(name = "patient_id")private Integer patientId;/*** 描述*/@ApiModelProperty(value = "描述", required = false, dataType = "String")@Column(name = "remarks")private String remarks;/*** 附件id*/@ApiModelProperty(value = "附件id", required = false, dataType = "String")@Column(name = "file_id")private String fileId;/*** 预约类型*/@ApiModelProperty(value = "预约类型", required = true, dataType = "Integer")@Column(name = "reservation_type")private Integer reservationType;/*** 医生id*/@ApiModelProperty(value = "医生id", required = false, dataType = "Integer")@Column(name = "doctor_id")private Integer doctorId;/*** 回复*/@ApiModelProperty(value = "回复", required = false, dataType = "String")@Column(name = "reply")private String reply;/*** 回复附件*/@ApiModelProperty(value = "回复附件", required = false, dataType = "String")@Column(name = "reply_files_id")private String replyFilesId;/*** 状态*/@ApiModelProperty(value = "状态", required = false, dataType = "Integer")@Column(name = "work_status")private Integer workStatus;/*** 是否已完成咨询(1是,0否)*/@ApiModelProperty(value = "是否已完成咨询(1是,0否)", required = false, dataType = "Integer")@Column(name = "isfinish")private Integer isfinish;/*** 完成咨询的时间*/@ApiModelProperty(value = "完成咨询的时间", required = false, dataType = "Date")@Column(name = "finish_time")private Date finishTime;/*** 创建时间*/@ApiModelProperty(value = "创建时间", required = false, dataType = "Date")@Column(name = "create_time")private Date createTime;
3.医生添加排班或修改排班方法
public void addOrUpdateList(List<RqriGuidanceTime> list) {// 查询数据库中已有排班SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("HH:mm");SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");ArrayList<String> collect = new ArrayList<>();for (RqriGuidanceTime rqriGuidanceTime : list) {collect.add(simpleDateFormat.format(rqriGuidanceTime.getDate()));}List<String> list_date = collect.stream().distinct().collect(Collectors.toList());List<RqriGuidanceTime> rqriGuidanceTimes = rqriGuidanceTimeMapper.selectByDateList(list_date);// 已有的排班与修改的排班HashMap<String, List<RqriGuidanceTime>> hashMap_update = new HashMap<>();for (String item : list_date) {ArrayList<RqriGuidanceTime> list_update = new ArrayList<>();// 添加已有排班for (int j = 0; j < rqriGuidanceTimes.size(); j++) {if (simpleDateFormat.format(rqriGuidanceTimes.get(j).getDate()).equals(item)) {list_update.add(rqriGuidanceTimes.get(j));}}// 修改已有排班for (RqriGuidanceTime rqriGuidanceTime : list) {if (simpleDateFormat.format(rqriGuidanceTime.getDate()).equals(item) && rqriGuidanceTime.getGuidanceTimeId() != null) {for (int k = 0; k < list_update.size(); k++) {if (rqriGuidanceTime.getGuidanceTimeId().equals(list_update.get(k).getGuidanceTimeId())) {// 是否被预约if (!Objects.equals(list_update.get(k).getNum(), list_update.get(k).getResidue())) {String format = simpleDateFormat1.format(rqriGuidanceTime.getStarttime());String format1 = simpleDateFormat1.format(rqriGuidanceTime.getEndtime());throw new Exception("该时间点已被预约,不可修改!错误时间点:" + item + "," + format + "-" + format1);} else {list_update.set(k, rqriGuidanceTime);}}}}}hashMap_update.put(item, list_update);}// 新增的排班HashMap<String, List<RqriGuidanceTime>> hashMap_add = new HashMap<>();for (String value : list_date) {ArrayList<RqriGuidanceTime> list_add = new ArrayList<>();for (RqriGuidanceTime rqriGuidanceTime : list) {if (simpleDateFormat.format(rqriGuidanceTime.getDate()).equals(value) && rqriGuidanceTime.getGuidanceTimeId() == null) {list_add.add(rqriGuidanceTime);}}hashMap_add.put(value, list_add);}// 校验SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");for (String s : list_date) {List<Integer> list_standard = Arrays.asList(new Integer[2400]);for (int j = 0; j < 2400; j++) {list_standard.set(j, 1); // 1 表示可以选}// 已有的排班与修改的排班List<RqriGuidanceTime> rqriGuidanceTimes_update = hashMap_update.get(s);for (RqriGuidanceTime guidanceTime : rqriGuidanceTimes_update) {String starttime = sdf.format(guidanceTime.getStarttime());String endtime = sdf.format(guidanceTime.getEndtime());int start = Integer.parseInt(starttime.replace(":", ""));int end = Integer.parseInt(endtime.replace(":", ""));if (!(start < end)) {throw new Exception("时间设置错误,错误时间点:" + s + "," + starttime + "-" + endtime);}for (int k = start + 1; k < end; k++) {if (list_standard.get(k) == 0) {throw new Exception("该时间与其他时间点冲突,错误时间点:" + s + "," + starttime + "-" + endtime);} else {list_standard.set(k, 0);}}}// 新增的排班List<RqriGuidanceTime> rqriGuidanceTimes_add = hashMap_add.get(s);for (RqriGuidanceTime rqriGuidanceTime : rqriGuidanceTimes_add) {String starttime = sdf.format(rqriGuidanceTime.getStarttime());String endtime = sdf.format(rqriGuidanceTime.getEndtime());int start = Integer.parseInt(starttime.replace(":", ""));int end = Integer.parseInt(endtime.replace(":", ""));if (!(start < end)) {throw new Exception("时间设置错误,错误时间点:" + s + "," + starttime + "-" + endtime);}for (int k = start + 1; k < end; k++) {if (list_standard.get(k) == 0) {throw new Exception("该时间与其他时间点冲突,错误时间点:" + s + "," + starttime + "-" + endtime);} else {list_standard.set(k, 0);}}}}ArrayList<RqriGuidanceTime> list_update = new ArrayList<>();for (List<RqriGuidanceTime> update : hashMap_update.values()) {list_update.addAll(update);}for (RqriGuidanceTime rqriGuidanceTime : list_update) {rqriGuidanceTime.setResidue(rqriGuidanceTime.getNum());rqriGuidanceTimeMapper.updateByPrimaryKey(rqriGuidanceTime);//插入到redisresidueAddRedis(rqriGuidanceTime.getDate(), rqriGuidanceTime.getGuidanceTimeId().toString(), rqriGuidanceTime.getResidue());}ArrayList<RqriGuidanceTime> list_add = new ArrayList<>();for (List<RqriGuidanceTime> add : hashMap_add.values()) {list_add.addAll(add);}for (RqriGuidanceTime rqriGuidanceTime : list_add) {rqriGuidanceTime.setResidue(rqriGuidanceTime.getNum());}if (list_add.size() > 0) {rqriGuidanceTimeMapper.insertList(list_add);for (RqriGuidanceTime guidanceTime : list_add) {//插入到redisresidueAddRedis(guidanceTime.getDate(), guidanceTime.getGuidanceTimeId().toString(), guidanceTime.getResidue());}}}private static final String RESERVATION = "RESERVATION_";private void residueAddRedis(Date date, String guidanceTimeId, Integer residue) {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");// 将 Date 对象转换为字符串String[] split = dateFormat.format(date).split("-");int year = Integer.parseInt(split[0]);int month = Integer.parseInt(split[1]);int day = Integer.parseInt(split[2]);// 获取当前日期和时间LocalDateTime now = LocalDateTime.now();// 获取过期日期LocalDateTime endDate = LocalDateTime.of(year, month, day, 0, 0, 0, 0);// 计算当前日期和时间到过期日期开始时间的时间差Duration duration = Duration.between(now, endDate);//过期时间秒long seconds = duration.getSeconds();//初始化到redisredisUtils.set(RESERVATION + guidanceTimeId, residue, seconds);}
4.患者预约方法
public void save(RqriGuidanceTimeRelation rqriGuidanceTimeRelation) {boolean b = reservationService.makeReservation(rqriGuidanceTimeRelation.getGuidanceTimeId());if (!b) {throw new BusinessException("该时段已无预约次数");}RqriGuidanceTime rqriGuidanceTime = rqriGuidanceTimelMapper.selectByPrimaryKey(rqriGuidanceTimeRelation.getGuidanceTimeId());Integer residue = rqriGuidanceTime.getResidue();// 可预约次数减1rqriGuidanceTime.setResidue(residue - 1);rqriGuidanceTimelMapper.updateByPrimaryKey(rqriGuidanceTime);Integer guidanceTimeId = rqriGuidanceTime.getGuidanceTimeId();redisUtils.decr(RESERVATION + guidanceTimeId, 1);// 添加预约信息rqriGuidanceTimeRelation.setIsfinish(0);rqriGuidanceTimeRelation.setCreateTime(new Date());rqriGuidanceTimeRelationMapper.insertSelective(rqriGuidanceTimeRelation);}public boolean makeReservation(Integer guidanceTimeId) {String key = RESERVATION + guidanceTimeId.toString();// 获取 Redisson 的分布式锁RLock lock = redissonClient.getLock(RESERVATION_LOCK);try {// 尝试获取锁lock.lock();// 使用 Redis 的原子操作来减少可预约数量Long availableTickets = redisTemplate.opsForValue().decrement(key);if (availableTickets < 0) {// 预约已满,预约失败,需要将可预约数量还原redisTemplate.opsForValue().increment(key);return false;}// 预约成功return true;} finally {// 释放锁lock.unlock();}}
5.患者修改预约
public void update(Integer reservationId, Integer guidanceTimeId) {//判断新的预约是否有次数可以 有的话 - 1boolean b = reservationService.makeReservation(guidanceTimeId);if (!b) {throw new Exception("该时段已无预约次数");}//查询新的时段是RqriGuidanceTime newGuidanceTime = rqriGuidanceTimelMapper.selectByPrimaryKey(guidanceTimeId);
// Integer residue = newGuidanceTime.getResidue();
// if (residue == 0) {
// throw new Exception("该时段已无预约次数");
// }//根据预约信息id 查询原预约时段idRqriGuidanceTimeRelation rqriGuidanceTimeRelation = rqriGuidanceTimeRelationMapper.selectByPrimaryKey(reservationId);//根据原预约时段id获取原预约时段数据RqriGuidanceTime old = rqriGuidanceTimelMapper.selectByPrimaryKey(rqriGuidanceTimeRelation.getGuidanceTimeId());//原预约时段次数+ 1redisUtils.incr(RESERVATION + old.getGuidanceTimeId(), 1);old.setResidue(old.getResidue() + 1);//更新原时段rqriGuidanceTimelMapper.updateByPrimaryKey(old);//新预约时段剩余次数-1newGuidanceTime.setResidue(newGuidanceTime.getResidue() - 1);rqriGuidanceTimelMapper.updateByPrimaryKey(newGuidanceTime);//更新预约详情rqriGuidanceTimeRelation.setGuidanceTimeId(guidanceTimeId);rqriGuidanceTimeRelationMapper.updateByPrimaryKey(rqriGuidanceTimeRelation);}
6.患者取消预约
public void delete(RqriGuidanceTimeRelation rqriGuidanceTimeRelation) throws ParseException {RqriGuidanceTime rqriGuidanceTime = rqriGuidanceTimelMapper.selectByPrimaryKey(rqriGuidanceTimeRelation.getGuidanceTimeId());rqriGuidanceTime.setResidue(rqriGuidanceTime.getResidue() + 1);rqriGuidanceTimelMapper.updateByPrimaryKey(rqriGuidanceTime);rqriGuidanceTimeRelationMapper.delete(rqriGuidanceTimeRelation);redisUtils.incr(RESERVATION + rqriGuidanceTimeRelation.getGuidanceTimeId(), 1);}
相关文章:
java实现医院门诊排班与预约系统【代码】
文章目录 前言一、遇到的问题二、实现过程1.数据库设计2.实体类3.医生添加排班或修改排班方法4.患者预约方法5.患者修改预约6.患者取消预约 前言 该文章从实际需求出发,实现医生设置自身排班与患者预约功能。 一、遇到的问题 1、医生设置的排班表不能有时间上的冲…...
8.Redis-set
Set 常用命令saddsmemberssismemberscardspopsmovesrem集合间操作sinter 交集sinterstoresunion 并集sunionstoresdiff 差集sdiffstore 命令总结 内部编码应用场景使用 set来保存用户的“标签” set(集合)就是把一些有关联的数据放刀一起。 它与list的区别如下: 集合…...
电子厂生产管理系统解决方案
越来越多的企业开始意识到数字化转型的重要性。在这个过程中,生产型企业面临着许多挑战,例如如何提高生产效率、节省企业资源以及改善生产工艺流程和产品质量。有一种解决方案可以帮助企业应对这些挑战,那就是生产管理系统。 生产管理系统是一…...
ARM DIY(五)摄像头调试
前言 今天,就着摄像头的调试,从嵌入式工程师的角度,介绍如何从无到有,一步一步地调出一款设备。 摄像头型号:OV2640 开发步骤 分为 2 个阶段 5 个步骤 阶段一: 设备树、驱动、硬件 阶段二: 应…...
hadoop2.2.0伪分布式搭建
1.准备Linux环境 1.0点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet ip 设置网段:192.168.1.0 子网掩码:255.255.255.0 -> apply -> ok 回到windows --> 打开…...
高级IO(select、poll、epoll)
在介绍本文之前,先提出一个问题 什么是IO? 等数据拷贝 1.等 - IO事件就绪(检测功能成分) 2.数据拷贝 高效的IO就是:单位时间,等的比重越小,IO的效率越高 五种IO模型 IO模型: 阻塞式…...
Ceph基础知识和基础架构认识
1 Ceph基础介绍 Ceph是一个可靠地、自动重均衡、自动恢复的分布式存储系统,根据场景划分可以将Ceph分为三大块,分别是对象存储、块设备存储和文件系统服务。在虚拟化领域里,比较常用到的是Ceph的块设备存储,比如在OpenStack项目…...
【C++】快速排序的学习和介绍
前言 本篇文章我们先会学习快速排序这个算法,之后我们会学习sort这个函数 分治算法 在学习快速排序之前,我们先来学习一下分治算法,快速排序就是分治算法的一种,下面是分治算法的介绍, 分治算法,就是”…...
第九章 动态规划part12(代码随想录)
309.最佳买卖股票时机含冷冻期 1. 确定dp数组(dp table)以及下标的含义 dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。 2. 确定递推公式 拆分卖出股票状态是因为冷冻期前一天一定是具体卖出股票状态。 状态一 dp[i][0]&…...
ssm珠宝首饰交易平台源码和论文
ssm珠宝首饰交易平台源码和论文101 开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 技术:ssm 摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势&a…...
交互设计都有哪些准则?
UI交互设计的本质不是完全基于用户的需求,而是交互设计师需要学习根据用户描述的产品形式来了解用户需要什么。 在交互设计过程中,遵循科学交互设计的本质是整个交互设计过程的重要组成部分,这与产品使用过程中给用户带来的体验密切相关。本…...
【MySQL】从哪几个角度分析数据库失败的原因?
总体评估MySQL服务器感谢 💖 总体评估 当发现数据库出现问题时,我们首先应该从全局的角度考虑架构中的所有组件。包括: 服务器(数据库和应用程序) 存储:存储故障可能导致关键信息丢失网络接口:…...
Spring Boot 的核心注解SpringBootApplication
SpringBootApplication 包括的注解 SpringBootConfiguration 组合了 Configuration 注解,实现配置文件的功能。 EnableAutoConfiguration 打开自动配置的功能,也可以关闭某个自动配置的选项, 例如:java 如关闭数据源自动配置功…...
自助式数据分析平台:JVS智能BI功能介绍(一)数据源
一、数据源配置 数据源概述 数据源是JVS-智能BI支持多种数据形态的基础,核心的目标是将不同的数据来源通过统一接入,实现将不同的数据实现统一的数据加工、数据应用。目前JVS-智能BI主要支持3种形态的数据:数据库、API、离线文件。 界面介…...
CSS魔术师Houdini,用浏览器引擎实现高级CSS效果
开门见山,直接上货 🔍 CSS Houdini是什么? “Houdini”一词引用自“Harry Houdini”,他是一位20世纪的著名魔术师,亦被称为史上最伟大的魔术师、逃脱术师及特级表演者。 我们都知道,浏览器在渲染网页显示样…...
DC/DC开关电源学习笔记(二)开关电源的分类
(二)开关电源的分类 1.DC/DC类开关电源2.AC/DC变换器3.电路结构分类4.功率开关管分类5.电路拓扑分类 根据变换方式,电源产品有下列四大类; (1):第一大类:AC/DC开关电源; …...
conda创建python虚拟环境
1.查看当前存在那些虚拟环境 conda env list conda info -e 2.conda安装虚拟环境 conda create -n my_env_name python3.6 2.1在anaconda下改变python版本 当前3.7 安装3.7 conda create -n py37 python3.7 conda activate py37 conda create -n py37 python3.7conda a…...
Python 操作 MongoDB 数据库介绍
MongoDB 是一款面向文档型的 NoSQL 数据库,是一个基于分布式文件存储的开源的非关系型数据库系统,其内容是以 K/V 形式存储,结构不固定,它的字段值可以包含其他文档、数组和文档数组等。其采用的 BSON(二进制 JSON &am…...
【ES6】Generator 函数
Generator 函数是 ES6 引入的一种新的函数类型,它既可以生成一个序列,又可以在某个条件下停止执行,并在需要时恢复执行。Generator 函数非常适合处理那些需要按需计算的场景,例如处理大数据、生成随机数等。 Generator 函数的基本…...
「操作系统」1. 基础
前言:操作系统基础八股文 文章目录 一 、操作系统基础1.1 什么是操作系统?1.2 什么是系统调用1.3 什么是中断 🚀 作者简介:作为某云服务提供商的后端开发人员,我将在这里与大家简要分享一些实用的开发小技巧。在我的职…...
嵌入式网络硬件设计避坑指南:如何为你的SOC选配合适的PHY芯片与接口(MII/RMII实战解析)
嵌入式网络硬件设计避坑指南:如何为你的SOC选配合适的PHY芯片与接口(MII/RMII实战解析) 在嵌入式系统设计中,网络功能已成为现代智能设备的标配需求。无论是工业控制、物联网终端还是消费电子产品,稳定可靠的网络连接往…...
Android Studio中文界面完整汉化指南:三步打造母语开发环境
Android Studio中文界面完整汉化指南:三步打造母语开发环境 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack 还在为And…...
别再死记FPN公式了!用PyTorch手把手带你画一遍特征金字塔的‘数据流图’
用PyTorch动态可视化FPN特征金字塔的数据流动 在目标检测领域,特征金字塔网络(FPN)已经成为处理多尺度目标的标配组件。但很多开发者虽然能背诵FPN的结构图,却对特征图在金字塔各层之间的流动变化缺乏直观感受。本文将带您用PyTor…...
UCCL:GPU网络传输的性能优化与创新
1. UCCL:GPU网络传输的革命性创新在分布式机器学习训练场景中,GPU集群间的通信效率往往成为制约系统整体性能的关键瓶颈。传统基于TCP/IP的传输协议由于内核协议栈处理和多次数据拷贝等问题,难以满足现代AI训练任务对低延迟和高带宽的严苛要求…...
从伺服电机到总线端子:手把手教你用EtherCAT搭建一个简易的‘两轴’运动控制Demo
从伺服电机到总线端子:手把手构建EtherCAT两轴运动控制原型 在工业自动化领域,精确的运动控制往往意味着更高的生产效率和更稳定的产品质量。想象一下,当你需要让两个机械臂协同完成装配任务时,如何确保它们的动作像钟表齿轮般精准…...
第11篇 安全配置实战:SASL_SSL + SCRAM-SHA-512
第11篇:安全配置实战 —— SASL_SSL + SCRAM-SHA-512 生产落地 系列:Kafka Spring Boot:参数精讲与生产落地实战 本篇关键词:security.protocol SASL SCRAM-SHA-512 SSL TrustStore 生产安全配置 📌 本篇导读 内网开发环境用 PLAINTEXT 完全没问题。但一旦涉及: 云…...
告别‘天书’!手把手教你用vdex2dex、odex2smali等工具,把Android应用的vdex/odex/cdex转成可读的dex文件
Android逆向工程实战:从vdex/odex/cdex到可读dex的完整指南 当你兴致勃勃地打开一个APK文件准备分析时,却发现里面只有vdex、odex或cdex文件,用JADX直接打开全是乱码——这种挫败感每个逆向工程师都经历过。本文将带你一步步破解这些"天…...
5秒完成B站缓存视频转换:m4s到MP4无损转换完整指南
5秒完成B站缓存视频转换:m4s到MP4无损转换完整指南 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾为B站缓存视频无法在其他…...
如何3步在Mac上运行Windows软件:Whisky终极免费方案
如何3步在Mac上运行Windows软件:Whisky终极免费方案 【免费下载链接】Whisky A modern Wine wrapper for macOS built with SwiftUI 项目地址: https://gitcode.com/gh_mirrors/wh/Whisky 想在Mac上运行Windows软件却不想安装虚拟机?Whisky正是你…...
Sentaurus TCAD实战:手把手教你提取NPN三极管的Gummel-Poon模型参数(SPICE建模必备)
Sentaurus TCAD实战:从Gummel曲线到SPICE模型参数的完整提取流程 在半导体器件设计与电路仿真中,准确的三极管模型参数是确保仿真结果可靠性的关键。传统方法往往依赖器件手册提供的典型参数,但针对特定工艺定制的器件,这些参数可…...
