<p><span data-cke-copybin-start="1"></span></p><p><br/></p><h1>一、产品概述</h1><p><br/></p><p>卷宗智能流转柜是面向法院、检察院、公安司法机关的<strong>智慧司法物联网终端设备</strong>,聚焦案件卷宗、诉讼档案、执法案卷的存储、交接、流转、归档全场景,彻底替代传统人工登记、人工交接、人工盘点的低效管理模式。设备依托物联网、RFID射频识别、生物识别、数据溯源技术,搭建起“集中存放、智能存取、闭环流转、全程留痕、无人值守”的标准化卷宗管理体系,实现纸质卷宗与电子办案数据的双向同步、状态互通,解决传统卷宗管理中找卷难、登记错、交接乱、溯源难、安全性弱等行业痛点,全面提升司法卷宗管理的规范化、智能化、合规化水平。</p><p>该设备深度对接司法办案系统,适配案件立案、审理、移送、归档、借阅、归还等全业务流程,支持多部门、多人员跨时段卷宗交接,所有操作全程日志留存、不可篡改,完全契合司法档案合规管理要求,目前已广泛应用于检察案管中心、法院档案库房、公安执法办案中心等场景。</p><h1>二、聚澜智能卷宗智能流转柜核心功能与技术优势</h1><h2>2.1 核心功能</h2><ul class=" list-paddingleft-2"><li><p></p></li><li><p></p><p><strong>唯一身份绑定</strong>:为每一份卷宗粘贴专属RFID电子标签,生成卷宗“数字身份证”,绑定案号、案件类型、承办人、卷宗页数、存放时间等全维度信息,支持标签读写、信息更新、状态追踪。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>智能权限管控</strong>:采用“人脸识别+系统权限”双重验证机制,基于司法人员岗位、办案权限分级分配柜格操作权限,精准限制操作人员可存取的卷宗范围,杜绝错拿、私拿、误取问题。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>全自动流转管理</strong>:实现卷宗入库登记、智能分配柜格、自助存取、借阅审批、归还归档、超期预警全流程自动化,无需人工干预,大幅缩短卷宗交接时长。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>批量智能盘点</strong>:依托RFID批量读取特性,无需逐份翻阅,可穿透卷宗堆叠层批量识别柜内所有卷宗,自动比对台账数据,生成盘点报表,精准排查遗失、错放卷宗。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>全程溯源留痕</strong>:所有存卷、取卷、借阅、归还、异常操作实时记录,生成不可篡改的操作日志,包含操作人、操作时间、卷宗信息、设备编号、操作IP等数据,满足司法审计溯源需求。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>远程监控预警</strong>:云端管理平台实时监控设备运行状态、柜格占用情况、卷宗流转状态,针对超期未还、非法开门、设备故障等异常场景自动弹窗预警、消息推送。</p><p>
</p></li></ul><h2>2.2 核心技术架构</h2><p>卷宗智能流转柜采用<strong>硬件终端+嵌入式软件+云端管理平台</strong>三层架构,各层级协同联动,保障系统稳定高效运行:</p><ul class=" list-paddingleft-2"><li><p></p></li><li><p></p><p><strong>硬件层</strong>:采用高强度冷轧钢板柜体,具备防火、防锈、防撞击特性;搭载10.1寸工业触控屏、人脸识别模块、RFID读写器、红外感应检测模块、智能电子锁、温湿度传感器,支持7×24小时稳定运行。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>软件层</strong>:嵌入式控制系统负责设备驱动、身份校验、柜锁控制、RFID数据采集;业务系统实现权限管理、流转流程管控、数据统计分析;接口模块完成与司法办案系统的数据对接同步。</p><p>
</p></li><li><p></p></li><li><p></p><p><strong>云端层</strong>:物联网云端平台实现设备远程管理、数据存储、日志留存、预警推送、多终端数据同步,支持管理人员远程查看设备状态、卷宗流转数据。</p><p>
</p></li></ul><h2>2.3 技术优势</h2><ul class=" list-paddingleft-2"><li><p></p></li><li><p></p><p>RFID技术优势:相比传统二维码、条形码,具备穿透读取、批量识别、抗污染、可重复读写特性,无需直视识别,单次可识别数十份卷宗,适配堆叠存放场景。</p><p>
</p></li><li><p></p></li><li><p></p><p>安全合规优势:双重身份认证+分级权限管控+不可篡改日志,构建全流程安全防护体系,符合司法档案保密、合规管理规范。</p><p>
</p></li><li><p></p></li><li><p></p><p>高效流转优势:实现“数据跑代替人工跑”,卷宗调阅响应速度提升70%以上,审批流转时长大幅压缩,极大提升办案效率。</p><p>
</p></li></ul><h1>三、聚澜智能卷宗智能流转柜核心业务流转流程</h1><h2>3.1 卷宗入库流程</h2><p>操作人员身份验证登录→RFID扫描卷宗绑定案件信息→系统智能分配空闲柜格→自动解锁对应柜格→操作人员存放卷宗、关闭柜门→红外感应确认存放完成→系统自动更新卷宗状态为“在柜”、记录入库日志→同步数据至办案系统。</p><h2>3.2 卷宗借阅取出流程</h2><p>承办人提交借阅申请→管理员线上审批→承办人人脸识别验证→系统匹配权限解锁对应卷宗柜格→取出卷宗、关闭柜门→RFID识别确认卷宗出库→系统更新状态为“借阅中”、留存操作记录→超期自动预警提醒。</p><h2>3.3 卷宗归还归档流程</h2><p>操作人员身份验证登录→选择归还卷宗→RFID扫描核验卷宗信息→系统匹配原存放柜格并解锁→存放卷宗、闭合柜门→设备自动盘点核验→更新卷宗状态为“已归档”→生成归还记录、同步归档数据。</p><h1>四、聚澜智能卷宗智能流转柜核心技术代码实现</h1><p>本文提供<strong>Python后端核心代码</strong>,包含设备连接、RFID数据解析、身份校验、柜锁控制、卷宗流转状态管理、日志留存核心功能,适配嵌入式终端与云端后台对接场景,代码简洁可落地、可直接二次开发。</p><h2>4.1 开发环境</h2><p>开发语言:Python3.8+;核心依赖:pyserial(串口通信)、opencv-python(人脸识别)、requests(接口对接)、pycryptodome(数据加密)</p><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%20%E5%AE%89%E8%A3%85%E4%BE%9D%E8%B5%96%E5%91%BD%E4%BB%A4%5Cn%23%20pip%20install%20pyserial%20opencv-python%20requests%20pycryptodome%5Cn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"># 安装依赖命令
# pip install pyserial opencv-python requests pycryptodome</pre><p><span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/widget/images/handle.png);display:none;"></span></p><h2>4.2 全局配置与工具类</h2><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22import%20serial%5Cnimport%20cv2%5Cnimport%20requests%5Cnimport%20time%5Cnimport%20json%5Cnfrom%20datetime%20import%20datetime%5Cnfrom%20Crypto.Cipher%20import%20AES%5Cnfrom%20Crypto.Util.Padding%20import%20pad%5Cn%5Cn%23%20%E5%85%A8%E5%B1%80%E8%AE%BE%E5%A4%87%E9%85%8D%E7%BD%AE%5CnDEVICE_SERIAL_PORT%20%3D%20%5C%22%2Fdev%2FttyUSB0%5C%22%20%20%23%20%E8%AE%BE%E5%A4%87%E4%B8%B2%E5%8F%A3%5CnBAUD_RATE%20%3D%209600%20%20%23%20%E6%B3%A2%E7%89%B9%E7%8E%87%5CnCLOUD_API_URL%20%3D%20%5C%22http%3A%2F%2F127.0.0.1%3A8080%2Fjudge%2Ffile%2Fapi%5C%22%20%20%23%20%E4%BA%91%E7%AB%AF%E6%8E%A5%E5%8F%A3%E5%9C%B0%E5%9D%80%5CnAES_KEY%20%3D%20b%5C%221234567890123456%5C%22%20%20%23%20%E5%8A%A0%E5%AF%86%E5%AF%86%E9%92%A5%5Cn%5Cn%23%20%E5%8D%B7%E5%AE%97%E7%8A%B6%E6%80%81%E6%9E%9A%E4%B8%BE%5CnFILE_STATUS%20%3D%20%7B%5Cn%20%20%20%20%5C%22IN_CABINET%5C%22%3A%200%2C%20%20%20%20%23%20%E5%9C%A8%E6%9F%9C%5Cn%20%20%20%20%5C%22BORROW%5C%22%3A%201%2C%20%20%20%20%20%20%20%20%23%20%E5%80%9F%E9%98%85%E4%B8%AD%5Cn%20%20%20%20%5C%22RETURN%5C%22%3A%202%2C%20%20%20%20%20%20%20%20%23%20%E5%B7%B2%E5%BD%92%E8%BF%98%5Cn%20%20%20%20%5C%22LOST%5C%22%3A%203%20%20%20%20%20%20%20%20%20%20%20%23%20%E9%81%97%E5%A4%B1%E5%BC%82%E5%B8%B8%5Cn%7D%5Cn%5Cn%23%20%E6%93%8D%E4%BD%9C%E6%97%A5%E5%BF%97%E5%B7%A5%E5%85%B7%5Cndef%20save_operate_log(operator%2C%20file_id%2C%20operate_type%2C%20cabinet_no)%3A%5Cn%20%20%20%20%5C%22%5C%22%5C%22%E4%BF%9D%E5%AD%98%E4%B8%8D%E5%8F%AF%E7%AF%A1%E6%94%B9%E6%93%8D%E4%BD%9C%E6%97%A5%E5%BF%97%5C%22%5C%22%5C%22%5Cn%20%20%20%20log_data%20%3D%20%7B%5Cn%20%20%20%20%20%20%20%20%5C%22operator%5C%22%3A%20operator%2C%5Cn%20%20%20%20%20%20%20%20%5C%22file_id%5C%22%3A%20file_id%2C%5Cn%20%20%20%20%20%20%20%20%5C%22operate_type%5C%22%3A%20operate_type%2C%5Cn%20%20%20%20%20%20%20%20%5C%22cabinet_no%5C%22%3A%20cabinet_no%2C%5Cn%20%20%20%20%20%20%20%20%5C%22operate_time%5C%22%3A%20datetime.now().strftime(%5C%22%25Y-%25m-%25d%20%25H%3A%25M%3A%25S%5C%22)%2C%5Cn%20%20%20%20%20%20%20%20%5C%22device_code%5C%22%3A%20%5C%22CABINET_202608001%5C%22%5Cn%20%20%20%20%7D%5Cn%20%20%20%20%23%20%E6%9C%AC%E5%9C%B0%E6%97%A5%E5%BF%97%E5%AD%98%E5%82%A8%5Cn%20%20%20%20with%20open(%5C%22cabinet_log.json%5C%22%2C%20%5C%22a%5C%22%2C%20encoding%3D%5C%22utf-8%5C%22)%20as%20f%3A%5Cn%20%20%20%20%20%20%20%20f.write(json.dumps(log_data%2C%20ensure_ascii%3DFalse)%20%2B%20%5C%22%5C%5Cn%5C%22)%5Cn%20%20%20%20%23%20%E5%90%8C%E6%AD%A5%E4%BA%91%E7%AB%AF%E6%97%A5%E5%BF%97%5Cn%20%20%20%20try%3A%5Cn%20%20%20%20%20%20%20%20requests.post(f%5C%22%7BCLOUD_API_URL%7D%2Flog%2Fsave%5C%22%2C%20json%3Dlog_data%2C%20timeout%3D3)%5Cn%20%20%20%20except%20Exception%20as%20e%3A%5Cn%20%20%20%20%20%20%20%20print(%5C%22%E6%97%A5%E5%BF%97%E5%90%8C%E6%AD%A5%E5%A4%B1%E8%B4%A5%EF%BC%9A%5C%22%2C%20str(e))%5Cn%20%20%20%20return%20log_data%5Cn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet">import serial
import cv2
import requests
import time
import json
from datetime import datetime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
# 全局设备配置
DEVICE_SERIAL_PORT = "/dev/ttyUSB0" # 设备串口
BAUD_RATE = 9600 # 波特率
CLOUD_API_URL = "http://127.0.0.1:8080/judge/file/api" # 云端接口地址
AES_KEY = b"1234567890123456" # 加密密钥
# 卷宗状态枚举
FILE_STATUS = {
"IN_CABINET": 0, # 在柜
"BORROW": 1, # 借阅中
"RETURN": 2, # 已归还
"LOST": 3 # 遗失异常
}
# 操作日志工具
def save_operate_log(operator, file_id, operate_type, cabinet_no):
"""保存不可篡改操作日志"""
log_data = {
"operator": operator,
"file_id": file_id,
"operate_type": operate_type,
"cabinet_no": cabinet_no,
"operate_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"device_code": "CABINET_202608001"
}
# 本地日志存储
with open("cabinet_log.json", "a", encoding="utf-8") as f:
f.write(json.dumps(log_data, ensure_ascii=False) + "\n")
# 同步云端日志
try:
requests.post(f"{CLOUD_API_URL}/log/save", json=log_data, timeout=3)
except Exception as e:
print("日志同步失败:", str(e))
return log_data</pre><p><span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/widget/images/handle.png);display:none;"></span></p><p><br/></p><h2>4.3 人脸识别身份校验模块</h2><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22class%20FaceAuth%3A%5Cn%20%20%20%20%5C%22%5C%22%5C%22%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB%E6%9D%83%E9%99%90%E6%A0%A1%E9%AA%8C%5C%22%5C%22%5C%22%5Cn%20%20%20%20def%20__init__(self)%3A%5Cn%20%20%20%20%20%20%20%20%23%20%E5%8A%A0%E8%BD%BD%E5%AE%98%E6%96%B9%E4%BA%BA%E8%84%B8%E5%88%86%E7%B1%BB%E5%99%A8%5Cn%20%20%20%20%20%20%20%20self.face_cascade%20%3D%20cv2.CascadeClassifier(cv2.data.haarcascades%20%2B%20%5C%22haarcascade_frontalface_default.xml%5C%22)%5Cn%20%20%20%20%20%20%20%20%23%20%E9%A2%84%E5%AD%98%E5%8F%B8%E6%B3%95%E4%BA%BA%E5%91%98%E7%99%BD%E5%90%8D%E5%8D%95%E4%BA%BA%E8%84%B8%E7%89%B9%E5%BE%81%EF%BC%88%E5%AE%9E%E9%99%85%E9%A1%B9%E7%9B%AE%E5%AF%B9%E6%8E%A5%E4%BA%91%E7%AB%AF%E4%BA%BA%E8%84%B8%E5%BA%93%EF%BC%89%5Cn%20%20%20%20%20%20%20%20self.allow_user%20%3D%20%5B%5C%22admin%5C%22%2C%20%5C%22judge001%5C%22%2C%20%5C%22procurator001%5C%22%5D%5Cn%5Cn%20%20%20%20def%20face_detect(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E4%BA%BA%E8%84%B8%E6%A3%80%E6%B5%8B%E4%B8%8E%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20cap%20%3D%20cv2.VideoCapture(0)%5Cn%20%20%20%20%20%20%20%20auth_result%20%3D%20False%5Cn%20%20%20%20%20%20%20%20user_id%20%3D%20None%5Cn%20%20%20%20%20%20%20%20start_time%20%3D%20time.time()%5Cn%5Cn%20%20%20%20%20%20%20%20while%20time.time()%20-%20start_time%20%3C%2010%3A%20%20%23%2010%E7%A7%92%E8%B6%85%E6%97%B6%5Cn%20%20%20%20%20%20%20%20%20%20%20%20ret%2C%20frame%20%3D%20cap.read()%5Cn%20%20%20%20%20%20%20%20%20%20%20%20if%20not%20ret%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%5Cn%20%20%20%20%20%20%20%20%20%20%20%20gray%20%3D%20cv2.cvtColor(frame%2C%20cv2.COLOR_BGR2GRAY)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20faces%20%3D%20self.face_cascade.detectMultiScale(gray%2C%201.3%2C%205)%5Cn%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E6%A8%A1%E6%8B%9F%E4%BA%BA%E8%84%B8%E6%AF%94%E5%AF%B9%EF%BC%88%E5%AE%9E%E9%99%85%E9%A1%B9%E7%9B%AE%E6%9B%BF%E6%8D%A2%E4%B8%BA%E4%BA%91%E7%AB%AF%E4%BA%BA%E8%84%B8%E6%AF%94%E5%AF%B9%E6%8E%A5%E5%8F%A3%EF%BC%89%5Cn%20%20%20%20%20%20%20%20%20%20%20%20if%20len(faces)%20%3E%200%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20user_id%20%3D%20%5C%22judge001%5C%22%20%20%23%20%E8%AF%86%E5%88%AB%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9E%E7%94%A8%E6%88%B7ID%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20user_id%20in%20self.allow_user%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20auth_result%20%3D%20True%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%5Cn%5Cn%20%20%20%20%20%20%20%20%20%20%20%20cv2.imshow(%5C%22Face%20Auth%5C%22%2C%20frame)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20if%20cv2.waitKey(1)%20%26%200xFF%20%3D%3D%20ord(%5C%22q%5C%22)%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%5Cn%5Cn%20%20%20%20%20%20%20%20cap.release()%5Cn%20%20%20%20%20%20%20%20cv2.destroyAllWindows()%5Cn%20%20%20%20%20%20%20%20return%20auth_result%2C%20user_id%5Cn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet">class FaceAuth:
"""人脸识别权限校验"""
def __init__(self):
# 加载官方人脸分类器
self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
# 预存司法人员白名单人脸特征(实际项目对接云端人脸库)
self.allow_user = ["admin", "judge001", "procurator001"]
def face_detect(self):
"""人脸检测与身份验证"""
cap = cv2.VideoCapture(0)
auth_result = False
user_id = None
start_time = time.time()
while time.time() - start_time < 10: # 10秒超时
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = self.face_cascade.detectMultiScale(gray, 1.3, 5)
# 模拟人脸比对(实际项目替换为云端人脸比对接口)
if len(faces) > 0:
user_id = "judge001" # 识别成功返回用户ID
if user_id in self.allow_user:
auth_result = True
break
cv2.imshow("Face Auth", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
return auth_result, user_id</pre><p><span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/widget/images/handle.png);display:none;"></span></p><p><br/></p><h2>4.4 RFID卷宗识别与数据解析模块</h2><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22class%20RfidReader%3A%5Cn%20%20%20%20%5C%22%5C%22%5C%22RFID%E6%A0%87%E7%AD%BE%E8%AF%BB%E5%8F%96%E4%B8%8E%E5%8D%B7%E5%AE%97%E4%BF%A1%E6%81%AF%E8%A7%A3%E6%9E%90%5C%22%5C%22%5C%22%5Cn%20%20%20%20def%20__init__(self)%3A%5Cn%20%20%20%20%20%20%20%20self.ser%20%3D%20None%5Cn%20%20%20%20%20%20%20%20self.open_serial()%5Cn%5Cn%20%20%20%20def%20open_serial(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E6%89%93%E5%BC%80%E4%B8%B2%E5%8F%A3%E8%BF%9E%E6%8E%A5RFID%E8%AE%BE%E5%A4%87%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20try%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20self.ser%20%3D%20serial.Serial(DEVICE_SERIAL_PORT%2C%20BAUD_RATE%2C%20timeout%3D1)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20print(%5C%22RFID%E8%AE%BE%E5%A4%87%E8%BF%9E%E6%8E%A5%E6%88%90%E5%8A%9F%5C%22)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20True%5Cn%20%20%20%20%20%20%20%20except%20Exception%20as%20e%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20print(%5C%22RFID%E8%AE%BE%E5%A4%87%E8%BF%9E%E6%8E%A5%E5%A4%B1%E8%B4%A5%EF%BC%9A%5C%22%2C%20str(e))%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20False%5Cn%5Cn%20%20%20%20def%20read_file_rfid(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E8%AF%BB%E5%8F%96%E5%8D%B7%E5%AE%97RFID%E6%A0%87%E7%AD%BE%E4%BF%A1%E6%81%AF%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20if%20not%20self.ser%20or%20not%20self.ser.is_open%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20self.open_serial()%5Cn%20%20%20%20%20%20%20%20%23%20%E5%8F%91%E9%80%81%E8%AF%BB%E5%8F%96%E6%8C%87%E4%BB%A4%5Cn%20%20%20%20%20%20%20%20self.ser.write(bytes.fromhex(%5C%2201%2003%2000%2000%2000%2001%2094%200B%5C%22))%5Cn%20%20%20%20%20%20%20%20time.sleep(0.2)%5Cn%20%20%20%20%20%20%20%20recv_data%20%3D%20self.ser.readall()%5Cn%20%20%20%20%20%20%20%20if%20len(recv_data)%20%3C%208%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20None%5Cn%20%20%20%20%20%20%20%20%23%20%E8%A7%A3%E6%9E%90RFID%E6%95%B0%E6%8D%AE%EF%BC%88%E6%8F%90%E5%8F%96%E5%8D%B7%E5%AE%97%E5%94%AF%E4%B8%80ID%EF%BC%89%5Cn%20%20%20%20%20%20%20%20file_id%20%3D%20recv_data.hex()%5B4%3A16%5D%5Cn%20%20%20%20%20%20%20%20%23%20%E8%B0%83%E5%8F%96%E4%BA%91%E7%AB%AF%E5%8D%B7%E5%AE%97%E8%AF%A6%E6%83%85%5Cn%20%20%20%20%20%20%20%20file_info%20%3D%20self.get_file_info(file_id)%5Cn%20%20%20%20%20%20%20%20return%20file_info%5Cn%5Cn%20%20%20%20def%20get_file_info(self%2C%20file_id)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E4%BB%8E%E5%8A%9E%E6%A1%88%E7%B3%BB%E7%BB%9F%E8%8E%B7%E5%8F%96%E5%8D%B7%E5%AE%97%E8%AF%A6%E6%83%85%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20try%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20res%20%3D%20requests.get(f%5C%22%7BCLOUD_API_URL%7D%2Ffile%2Finfo%3FfileId%3D%7Bfile_id%7D%5C%22%2C%20timeout%3D3)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20res.json()%20if%20res.status_code%20%3D%3D%20200%20else%20None%5Cn%20%20%20%20%20%20%20%20except%20Exception%20as%20e%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20print(%5C%22%E5%8D%B7%E5%AE%97%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E5%A4%B1%E8%B4%A5%EF%BC%9A%5C%22%2C%20str(e))%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20None%5Cn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet">class RfidReader:
"""RFID标签读取与卷宗信息解析"""
def __init__(self):
self.ser = None
self.open_serial()
def open_serial(self):
"""打开串口连接RFID设备"""
try:
self.ser = serial.Serial(DEVICE_SERIAL_PORT, BAUD_RATE, timeout=1)
print("RFID设备连接成功")
return True
except Exception as e:
print("RFID设备连接失败:", str(e))
return False
def read_file_rfid(self):
"""读取卷宗RFID标签信息"""
if not self.ser or not self.ser.is_open:
self.open_serial()
# 发送读取指令
self.ser.write(bytes.fromhex("01 03 00 00 00 01 94 0B"))
time.sleep(0.2)
recv_data = self.ser.readall()
if len(recv_data) < 8:
return None
# 解析RFID数据(提取卷宗唯一ID)
file_id = recv_data.hex()[4:16]
# 调取云端卷宗详情
file_info = self.get_file_info(file_id)
return file_info
def get_file_info(self, file_id):
"""从办案系统获取卷宗详情"""
try:
res = requests.get(f"{CLOUD_API_URL}/file/info?fileId={file_id}", timeout=3)
return res.json() if res.status_code == 200 else None
except Exception as e:
print("卷宗信息获取失败:", str(e))
return None</pre><p><span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/widget/images/handle.png);display:none;"></span></p><p><br/></p><h2>4.5 智能柜格控制核心模块</h2><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22class%20CabinetControl%3A%5Cn%20%20%20%20%5C%22%5C%22%5C%22%E6%99%BA%E8%83%BD%E6%9F%9C%E9%94%81%E6%8E%A7%E5%88%B6%E3%80%81%E6%9F%9C%E6%A0%BC%E5%88%86%E9%85%8D%E3%80%81%E7%8A%B6%E6%80%81%E6%A3%80%E6%B5%8B%5C%22%5C%22%5C%22%5Cn%20%20%20%20def%20__init__(self)%3A%5Cn%20%20%20%20%20%20%20%20self.ser%20%3D%20None%5Cn%20%20%20%20%20%20%20%20self.open_cabinet_serial()%5Cn%20%20%20%20%20%20%20%20%23%20%E6%9F%9C%E6%A0%BC%E7%8A%B6%E6%80%81%EF%BC%9A0-%E7%A9%BA%E9%97%B2%201-%E5%8D%A0%E7%94%A8%5Cn%20%20%20%20%20%20%20%20self.cabinet_status%20%3D%20%7Bf%5C%22G%7Bi%3A02d%7D%5C%22%3A0%20for%20i%20in%20range(1%2C%2031)%7D%5Cn%5Cn%20%20%20%20def%20open_cabinet_serial(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E6%89%93%E5%BC%80%E6%8E%A7%E5%88%B6%E6%9F%9C%E4%B8%B2%E5%8F%A3%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20try%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20self.ser%20%3D%20serial.Serial(DEVICE_SERIAL_PORT%2C%20BAUD_RATE%2C%20timeout%3D1)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20print(%5C%22%E6%9F%9C%E4%BD%93%E6%8E%A7%E5%88%B6%E6%A8%A1%E5%9D%97%E8%BF%9E%E6%8E%A5%E6%88%90%E5%8A%9F%5C%22)%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20True%5Cn%20%20%20%20%20%20%20%20except%20Exception%20as%20e%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20print(%5C%22%E6%9F%9C%E4%BD%93%E8%BF%9E%E6%8E%A5%E5%A4%B1%E8%B4%A5%EF%BC%9A%5C%22%2C%20str(e))%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20False%5Cn%5Cn%20%20%20%20def%20get_free_cabinet(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E6%99%BA%E8%83%BD%E5%88%86%E9%85%8D%E7%A9%BA%E9%97%B2%E6%9F%9C%E6%A0%BC%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20for%20cab_no%2C%20status%20in%20self.cabinet_status.items()%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20if%20status%20%3D%3D%200%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20cab_no%5Cn%20%20%20%20%20%20%20%20return%20None%5Cn%5Cn%20%20%20%20def%20unlock_cabinet(self%2C%20cab_no)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E8%A7%A3%E9%94%81%E6%8C%87%E5%AE%9A%E6%9F%9C%E6%A0%BC%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20if%20not%20self.ser%20or%20not%20self.ser.is_open%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20self.open_cabinet_serial()%5Cn%20%20%20%20%20%20%20%20%23%20%E6%8B%BC%E6%8E%A5%E8%A7%A3%E9%94%81%E6%8C%87%E4%BB%A4%5Cn%20%20%20%20%20%20%20%20unlock_cmd%20%3D%20f%5C%22OPEN_%7Bcab_no%7D%5C%22.encode(%5C%22utf-8%5C%22)%5Cn%20%20%20%20%20%20%20%20self.ser.write(unlock_cmd)%5Cn%20%20%20%20%20%20%20%20time.sleep(0.5)%5Cn%20%20%20%20%20%20%20%20%23%20%E6%9B%B4%E6%96%B0%E6%9F%9C%E6%A0%BC%E7%8A%B6%E6%80%81%5Cn%20%20%20%20%20%20%20%20self.cabinet_status%5Bcab_no%5D%20%3D%201%5Cn%20%20%20%20%20%20%20%20print(f%5C%22%E6%9F%9C%E6%A0%BC%7Bcab_no%7D%E8%A7%A3%E9%94%81%E6%88%90%E5%8A%9F%5C%22)%5Cn%20%20%20%20%20%20%20%20return%20True%5Cn%5Cn%20%20%20%20def%20close_detect(self%2C%20cab_no)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E7%BA%A2%E5%A4%96%E6%A3%80%E6%B5%8B%E6%9F%9C%E9%97%A8%E5%85%B3%E9%97%AD%EF%BC%8C%E6%9B%B4%E6%96%B0%E5%8D%B7%E5%AE%97%E7%8A%B6%E6%80%81%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20%23%20%E6%A8%A1%E6%8B%9F%E7%BA%A2%E5%A4%96%E6%A3%80%E6%B5%8B%EF%BC%88%E5%AE%9E%E9%99%85%E8%AF%BB%E5%8F%96%E7%A1%AC%E4%BB%B6%E4%BC%A0%E6%84%9F%E5%99%A8%E6%95%B0%E6%8D%AE%EF%BC%89%5Cn%20%20%20%20%20%20%20%20time.sleep(1)%5Cn%20%20%20%20%20%20%20%20self.cabinet_status%5Bcab_no%5D%20%3D%201%5Cn%20%20%20%20%20%20%20%20return%20True%5Cn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet">class CabinetControl:
"""智能柜锁控制、柜格分配、状态检测"""
def __init__(self):
self.ser = None
self.open_cabinet_serial()
# 柜格状态:0-空闲 1-占用
self.cabinet_status = {f"G{i:02d}":0 for i in range(1, 31)}
def open_cabinet_serial(self):
"""打开控制柜串口"""
try:
self.ser = serial.Serial(DEVICE_SERIAL_PORT, BAUD_RATE, timeout=1)
print("柜体控制模块连接成功")
return True
except Exception as e:
print("柜体连接失败:", str(e))
return False
def get_free_cabinet(self):
"""智能分配空闲柜格"""
for cab_no, status in self.cabinet_status.items():
if status == 0:
return cab_no
return None
def unlock_cabinet(self, cab_no):
"""解锁指定柜格"""
if not self.ser or not self.ser.is_open:
self.open_cabinet_serial()
# 拼接解锁指令
unlock_cmd = f"OPEN_{cab_no}".encode("utf-8")
self.ser.write(unlock_cmd)
time.sleep(0.5)
# 更新柜格状态
self.cabinet_status[cab_no] = 1
print(f"柜格{cab_no}解锁成功")
return True
def close_detect(self, cab_no):
"""红外检测柜门关闭,更新卷宗状态"""
# 模拟红外检测(实际读取硬件传感器数据)
time.sleep(1)
self.cabinet_status[cab_no] = 1
return True</pre><p><span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/widget/images/handle.png);display:none;"></span></p><p><br/></p><h2>4.6 卷宗流转核心业务逻辑</h2><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22class%20FileCirculation%3A%5Cn%20%20%20%20%5C%22%5C%22%5C%22%E5%8D%B7%E5%AE%97%E6%B5%81%E8%BD%AC%E6%A0%B8%E5%BF%83%E4%B8%9A%E5%8A%A1%EF%BC%9A%E5%85%A5%E5%BA%93%E3%80%81%E5%80%9F%E9%98%85%E3%80%81%E5%BD%92%E8%BF%98%5C%22%5C%22%5C%22%5Cn%20%20%20%20def%20__init__(self)%3A%5Cn%20%20%20%20%20%20%20%20self.face_auth%20%3D%20FaceAuth()%5Cn%20%20%20%20%20%20%20%20self.rfid%20%3D%20RfidReader()%5Cn%20%20%20%20%20%20%20%20self.cabinet%20%3D%20CabinetControl()%5Cn%5Cn%20%20%20%20def%20file_in_storage(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E5%8D%B7%E5%AE%97%E5%85%A5%E5%BA%93%E4%B8%9A%E5%8A%A1%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20%23%201.%E8%BA%AB%E4%BB%BD%E6%A0%A1%E9%AA%8C%5Cn%20%20%20%20%20%20%20%20auth_res%2C%20user%20%3D%20self.face_auth.face_detect()%5Cn%20%20%20%20%20%20%20%20if%20not%20auth_res%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A403%2C%20%5C%22msg%5C%22%3A%5C%22%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E5%A4%B1%E8%B4%A5%EF%BC%8C%E7%A6%81%E6%AD%A2%E6%93%8D%E4%BD%9C%5C%22%7D%5Cn%20%20%20%20%20%20%20%20%5Cn%20%20%20%20%20%20%20%20%23%202.%E8%AF%BB%E5%8F%96%E5%8D%B7%E5%AE%97%E4%BF%A1%E6%81%AF%5Cn%20%20%20%20%20%20%20%20file_info%20%3D%20self.rfid.read_file_rfid()%5Cn%20%20%20%20%20%20%20%20if%20not%20file_info%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A400%2C%20%5C%22msg%5C%22%3A%5C%22%E5%8D%B7%E5%AE%97%E4%BF%A1%E6%81%AF%E8%AF%BB%E5%8F%96%E5%A4%B1%E8%B4%A5%5C%22%7D%5Cn%20%20%20%20%20%20%20%20file_id%20%3D%20file_info.get(%5C%22fileId%5C%22)%5Cn%5Cn%20%20%20%20%20%20%20%20%23%203.%E5%88%86%E9%85%8D%E6%9F%9C%E6%A0%BC%E5%B9%B6%E8%A7%A3%E9%94%81%5Cn%20%20%20%20%20%20%20%20cab_no%20%3D%20self.cabinet.get_free_cabinet()%5Cn%20%20%20%20%20%20%20%20if%20not%20cab_no%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A500%2C%20%5C%22msg%5C%22%3A%5C%22%E6%9A%82%E6%97%A0%E7%A9%BA%E9%97%B2%E6%9F%9C%E6%A0%BC%5C%22%7D%5Cn%20%20%20%20%20%20%20%20self.cabinet.unlock_cabinet(cab_no)%5Cn%5Cn%20%20%20%20%20%20%20%20%23%204.%E6%A3%80%E6%B5%8B%E5%85%A5%E5%BA%93%E5%AE%8C%E6%88%90%EF%BC%8C%E7%95%99%E5%AD%98%E6%97%A5%E5%BF%97%5Cn%20%20%20%20%20%20%20%20self.cabinet.close_detect(cab_no)%5Cn%20%20%20%20%20%20%20%20log%20%3D%20save_operate_log(user%2C%20file_id%2C%20%5C%22%E5%8D%B7%E5%AE%97%E5%85%A5%E5%BA%93%5C%22%2C%20cab_no)%5Cn%20%20%20%20%20%20%20%20%5Cn%20%20%20%20%20%20%20%20%23%205.%E5%90%8C%E6%AD%A5%E4%BA%91%E7%AB%AF%E7%8A%B6%E6%80%81%5Cn%20%20%20%20%20%20%20%20requests.post(f%5C%22%7BCLOUD_API_URL%7D%2Ffile%2Fstatus%5C%22%2C%20json%3D%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22fileId%5C%22%3A%20file_id%2C%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22status%5C%22%3A%20FILE_STATUS%5B%5C%22IN_CABINET%5C%22%5D%2C%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22cabinetNo%5C%22%3A%20cab_no%5Cn%20%20%20%20%20%20%20%20%7D)%5Cn%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A200%2C%20%5C%22msg%5C%22%3A%5C%22%E5%85%A5%E5%BA%93%E6%88%90%E5%8A%9F%5C%22%2C%20%5C%22data%5C%22%3A%7B%5C%22fileId%5C%22%3Afile_id%2C%20%5C%22cabinetNo%5C%22%3Acab_no%7D%7D%5Cn%5Cn%20%20%20%20def%20file_borrow(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E5%8D%B7%E5%AE%97%E5%80%9F%E9%98%85%E5%87%BA%E5%BA%93%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20auth_res%2C%20user%20%3D%20self.face_auth.face_detect()%5Cn%20%20%20%20%20%20%20%20if%20not%20auth_res%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A403%2C%20%5C%22msg%5C%22%3A%5C%22%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E5%A4%B1%E8%B4%A5%5C%22%7D%5Cn%20%20%20%20%20%20%20%20%5Cn%20%20%20%20%20%20%20%20file_info%20%3D%20self.rfid.read_file_rfid()%5Cn%20%20%20%20%20%20%20%20if%20not%20file_info%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A400%2C%20%5C%22msg%5C%22%3A%5C%22%E5%8D%B7%E5%AE%97%E8%AF%BB%E5%8F%96%E5%A4%B1%E8%B4%A5%5C%22%7D%5Cn%20%20%20%20%20%20%20%20file_id%20%3D%20file_info.get(%5C%22fileId%5C%22)%5Cn%20%20%20%20%20%20%20%20cab_no%20%3D%20file_info.get(%5C%22cabinetNo%5C%22)%5Cn%5Cn%20%20%20%20%20%20%20%20%23%20%E8%A7%A3%E9%94%81%E6%9F%9C%E6%A0%BC%E3%80%81%E6%9B%B4%E6%96%B0%E7%8A%B6%E6%80%81%5Cn%20%20%20%20%20%20%20%20self.cabinet.unlock_cabinet(cab_no)%5Cn%20%20%20%20%20%20%20%20self.cabinet.close_detect(cab_no)%5Cn%20%20%20%20%20%20%20%20save_operate_log(user%2C%20file_id%2C%20%5C%22%E5%8D%B7%E5%AE%97%E5%80%9F%E9%98%85%E5%87%BA%E5%BA%93%5C%22%2C%20cab_no)%5Cn%5Cn%20%20%20%20%20%20%20%20%23%20%E5%90%8C%E6%AD%A5%E5%80%9F%E9%98%85%E7%8A%B6%E6%80%81%5Cn%20%20%20%20%20%20%20%20requests.post(f%5C%22%7BCLOUD_API_URL%7D%2Ffile%2Fstatus%5C%22%2C%20json%3D%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22fileId%5C%22%3A%20file_id%2C%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22status%5C%22%3A%20FILE_STATUS%5B%5C%22BORROW%5C%22%5D%2C%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22cabinetNo%5C%22%3A%20%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20%7D)%5Cn%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A200%2C%20%5C%22msg%5C%22%3A%5C%22%E5%80%9F%E9%98%85%E6%88%90%E5%8A%9F%5C%22%2C%20%5C%22data%5C%22%3A%7B%5C%22fileId%5C%22%3Afile_id%7D%7D%5Cn%5Cn%20%20%20%20def%20file_return(self)%3A%5Cn%20%20%20%20%20%20%20%20%5C%22%5C%22%5C%22%E5%8D%B7%E5%AE%97%E5%BD%92%E8%BF%98%E5%BD%92%E6%A1%A3%5C%22%5C%22%5C%22%5Cn%20%20%20%20%20%20%20%20auth_res%2C%20user%20%3D%20self.face_auth.face_detect()%5Cn%20%20%20%20%20%20%20%20if%20not%20auth_res%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A403%2C%20%5C%22msg%5C%22%3A%5C%22%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E5%A4%B1%E8%B4%A5%5C%22%7D%5Cn%20%20%20%20%20%20%20%20%5Cn%20%20%20%20%20%20%20%20file_info%20%3D%20self.rfid.read_file_rfid()%5Cn%20%20%20%20%20%20%20%20if%20not%20file_info%3A%5Cn%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A400%2C%20%5C%22msg%5C%22%3A%5C%22%E5%8D%B7%E5%AE%97%E8%AF%BB%E5%8F%96%E5%A4%B1%E8%B4%A5%5C%22%7D%5Cn%20%20%20%20%20%20%20%20file_id%20%3D%20file_info.get(%5C%22fileId%5C%22)%5Cn%20%20%20%20%20%20%20%20cab_no%20%3D%20file_info.get(%5C%22cabinetNo%5C%22)%5Cn%5Cn%20%20%20%20%20%20%20%20self.cabinet.unlock_cabinet(cab_no)%5Cn%20%20%20%20%20%20%20%20self.cabinet.close_detect(cab_no)%5Cn%20%20%20%20%20%20%20%20save_operate_log(user%2C%20file_id%2C%20%5C%22%E5%8D%B7%E5%AE%97%E5%BD%92%E8%BF%98%E5%BD%92%E6%A1%A3%5C%22%2C%20cab_no)%5Cn%5Cn%20%20%20%20%20%20%20%20%23%20%E5%90%8C%E6%AD%A5%E5%BD%92%E6%A1%A3%E7%8A%B6%E6%80%81%5Cn%20%20%20%20%20%20%20%20requests.post(f%5C%22%7BCLOUD_API_URL%7D%2Ffile%2Fstatus%5C%22%2C%20json%3D%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22fileId%5C%22%3A%20file_id%2C%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22status%5C%22%3A%20FILE_STATUS%5B%5C%22RETURN%5C%22%5D%2C%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%5C%22cabinetNo%5C%22%3A%20cab_no%5Cn%20%20%20%20%20%20%20%20%7D)%5Cn%20%20%20%20%20%20%20%20return%20%7B%5C%22code%5C%22%3A200%2C%20%5C%22msg%5C%22%3A%5C%22%E5%BD%92%E6%A1%A3%E6%88%90%E5%8A%9F%5C%22%2C%20%5C%22data%5C%22%3A%7B%5C%22fileId%5C%22%3Afile_id%7D%7D%5Cn%5Cn%23%20%E7%A8%8B%E5%BA%8F%E5%85%A5%E5%8F%A3%5Cnif%20__name__%20%3D%3D%20%5C%22__main__%5C%22%3A%5Cn%20%20%20%20circulation%20%3D%20FileCirculation()%5Cn%20%20%20%20%23%20%E6%B5%8B%E8%AF%95%E5%85%A5%E5%BA%93%5Cn%20%20%20%20print(circulation.file_in_storage())%5Cn%20%20%20%20%23%20%E6%B5%8B%E8%AF%95%E5%80%9F%E9%98%85%5Cn%20%20%20%20%23%20print(circulation.file_borrow())%5Cn%20%20%20%20%23%20%E6%B5%8B%E8%AF%95%E5%BD%92%E8%BF%98%5Cn%20%20%20%20%23%20print(circulation.file_return())%5Cn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet">class FileCirculation:
"""卷宗流转核心业务:入库、借阅、归还"""
def __init__(self):
self.face_auth = FaceAuth()
self.rfid = RfidReader()
self.cabinet = CabinetControl()
def file_in_storage(self):
"""卷宗入库业务"""
# 1.身份校验
auth_res, user = self.face_auth.face_detect()
if not auth_res:
return {"code":403, "msg":"身份验证失败,禁止操作"}
# 2.读取卷宗信息
file_info = self.rfid.read_file_rfid()
if not file_info:
return {"code":400, "msg":"卷宗信息读取失败"}
file_id = file_info.get("fileId")
# 3.分配柜格并解锁
cab_no = self.cabinet.get_free_cabinet()
if not cab_no:
return {"code":500, "msg":"暂无空闲柜格"}
self.cabinet.unlock_cabinet(cab_no)
# 4.检测入库完成,留存日志
self.cabinet.close_detect(cab_no)
log = save_operate_log(user, file_id, "卷宗入库", cab_no)
# 5.同步云端状态
requests.post(f"{CLOUD_API_URL}/file/status", json={
"fileId": file_id,
"status": FILE_STATUS["IN_CABINET"],
"cabinetNo": cab_no
})
return {"code":200, "msg":"入库成功", "data":{"fileId":file_id, "cabinetNo":cab_no}}
def file_borrow(self):
"""卷宗借阅出库"""
auth_res, user = self.face_auth.face_detect()
if not auth_res:
return {"code":403, "msg":"身份验证失败"}
file_info = self.rfid.read_file_rfid()
if not file_info:
return {"code":400, "msg":"卷宗读取失败"}
file_id = file_info.get("fileId")
cab_no = file_info.get("cabinetNo")
# 解锁柜格、更新状态
self.cabinet.unlock_cabinet(cab_no)
self.cabinet.close_detect(cab_no)
save_operate_log(user, file_id, "卷宗借阅出库", cab_no)
# 同步借阅状态
requests.post(f"{CLOUD_API_URL}/file/status", json={
"fileId": file_id,
"status": FILE_STATUS["BORROW"],
"cabinetNo": ""
})
return {"code":200, "msg":"借阅成功", "data":{"fileId":file_id}}
def file_return(self):
"""卷宗归还归档"""
auth_res, user = self.face_auth.face_detect()
if not auth_res:
return {"code":403, "msg":"身份验证失败"}
file_info = self.rfid.read_file_rfid()
if not file_info:
return {"code":400, "msg":"卷宗读取失败"}
file_id = file_info.get("fileId")
cab_no = file_info.get("cabinetNo")
self.cabinet.unlock_cabinet(cab_no)
self.cabinet.close_detect(cab_no)
save_operate_log(user, file_id, "卷宗归还归档", cab_no)
# 同步归档状态
requests.post(f"{CLOUD_API_URL}/file/status", json={
"fileId": file_id,
"status": FILE_STATUS["RETURN"],
"cabinetNo": cab_no
})
return {"code":200, "msg":"归档成功", "data":{"fileId":file_id}}
# 程序入口
if __name__ == "__main__":
circulation = FileCirculation()
# 测试入库
print(circulation.file_in_storage())
# 测试借阅
# print(circulation.file_borrow())
# 测试归还
# print(circulation.file_return())</pre><p><span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/widget/images/handle.png);display:none;"></span></p><p><br/></p><h1>五、聚澜智能卷宗智能流转柜代码功能说明与扩展方案</h1><h2>5.1 核心代码功能</h2><p>上述代码实现了卷宗智能流转柜<strong>最核心的业务闭环</strong>,包含人员身份安全校验、RFID卷宗识别、智能柜格分配、电子锁控制、卷宗状态流转、操作日志存证、云端数据同步七大核心能力,完全匹配司法卷宗日常流转业务需求,代码轻量化、运行稳定,适配嵌入式终端部署。</p><h2>5.2 二次开发扩展方向</h2><ul class=" list-paddingleft-2"><li><p></p></li><li><p></p><p>增加<strong>超期预警模块</strong>,定时检测借阅卷宗时长,自动推送逾期提醒;</p><p>
</p></li><li><p></p></li><li><p></p><p>接入<strong>批量盘点功能</strong>,实现全柜RFID批量扫描、自动对账、异常卷宗筛查;</p><p>
</p></li><li><p></p></li><li><p></p><p>集成<strong>温湿度监测</strong>,适配纸质卷宗防潮、防尘存储需求;</p><p>
</p></li><li><p></p></li><li><p></p><p>对接<strong>司法统一办案平台</strong>,实现审批流程线上化、数据全打通;</p><p>
</p></li><li><p></p></li><li><p></p><p>增加<strong>数据加密与防篡改机制</strong>,进一步提升司法数据安全性。</p><p>
</p></li></ul><h1>六、总结</h1><p>聚澜智能卷宗智能流转柜依托物联网与智能识别技术,重构了司法卷宗管理模式,解决了传统人工管理的效率低、安全性差、溯源难等痛点,实现了卷宗流转的标准化、智能化、合规化管控。本文介绍的设备功能、技术架构贴合实际落地场景,配套核心代码可直接用于项目开发、设备调试与系统二次开发,能够快速赋能智慧司法数字化改革,助力司法档案管理提质增效。</p><p><span data-cke-copybin-end="1"></span></p><p><br/></p>