加入导出案件日志功能

This commit is contained in:
27942
2026-02-01 18:17:40 +08:00
parent 5db0af8360
commit a03ef1cde8
2 changed files with 155 additions and 2 deletions

View File

@@ -1,7 +1,7 @@
from django.urls import path
from .models import Schedule
from .views import registration,registrationDetail,Project,Projectquerytype,ProjectDetail,EditProject,BidRegistration,BidDetail,registrationList,caseManagement,caseManagementDetail,CaseAttachmentUpload,CaseAttachmentUpdate,Uploadinvoice,InvoiceDetail,Log,LogDetail,accumulate,preFilingLinkedCases,Application,ApplicationDetail,WarehousingRegistration,WarehousingDetail,PlatformRegistration,PlatformDetail,EditPlatformDetail,DeletePlatformDetail,bulletin,BulletinDetail,EditBulletin,deleteBulletin,Lawyersdocuments,LawyersdocumentsDetail,LwaDetail,CreateSchedule,DeleteSchedule,ScheduleDetail,handleSchedule,AddRermission,DisplayRermission,DeleteRermission,EditRermission,addRole,DeleteRole,EditRole,displayRole,modifypermissions,getRolePermissions,DeleteRegistration,EditRegistration,DeleteProject,EditBid,DeleteBid,EditCase,DeleteCase,EditApplication,DeleteApplication,EditWarehousing,DeleteWarehousing,EditLawyerFlie,EditSchedule,TransferCase,CaseChangeRequestCreate,CaseChangeRequestList,CaseChangeRequestDetail,ProjectDropdownList,CaseDropdownList,ConflictSearch,CreateCaseTag,CaseTagList,CaseTagDetail,EditCaseTag,DeleteCaseTag,CaseTagDropdownList,CaseListByTag,SetCaseTags,PropagandaEit,addSystem,SystemList,eitSystem,deleteSystem
from .views import registration,registrationDetail,Project,Projectquerytype,ProjectDetail,EditProject,BidRegistration,BidDetail,registrationList,caseManagement,caseManagementDetail,CaseAttachmentUpload,CaseAttachmentUpdate,Uploadinvoice,InvoiceDetail,Log,LogDetail,accumulate,preFilingLinkedCases,Application,ApplicationDetail,WarehousingRegistration,WarehousingDetail,PlatformRegistration,PlatformDetail,EditPlatformDetail,DeletePlatformDetail,bulletin,BulletinDetail,EditBulletin,deleteBulletin,Lawyersdocuments,LawyersdocumentsDetail,LwaDetail,CreateSchedule,DeleteSchedule,ScheduleDetail,handleSchedule,AddRermission,DisplayRermission,DeleteRermission,EditRermission,addRole,DeleteRole,EditRole,displayRole,modifypermissions,getRolePermissions,DeleteRegistration,EditRegistration,DeleteProject,EditBid,DeleteBid,EditCase,DeleteCase,EditApplication,DeleteApplication,EditWarehousing,DeleteWarehousing,EditLawyerFlie,EditSchedule,TransferCase,CaseChangeRequestCreate,CaseChangeRequestList,CaseChangeRequestDetail,ProjectDropdownList,CaseDropdownList,ConflictSearch,CreateCaseTag,CaseTagList,CaseTagDetail,EditCaseTag,DeleteCaseTag,CaseTagDropdownList,CaseListByTag,SetCaseTags,PropagandaEit,addSystem,SystemList,eitSystem,deleteSystem,ExportCaseLogExcel
urlpatterns = [
path('register',registration.as_view(),name='register'),
@@ -85,5 +85,7 @@ urlpatterns = [
path('addSystem',addSystem.as_view(),name='addSystem'),
path('SystemList',SystemList.as_view(),name='SystemList'),
path('eitSystem',eitSystem.as_view(),name='eitSystem'),
path('deleteSystem',deleteSystem.as_view(),name='deleteSystem')
path('deleteSystem',deleteSystem.as_view(),name='deleteSystem'),
# 案件日志导出Excel
path('export-case-log-excel',ExportCaseLogExcel.as_view(),name='export-case-log-excel'),
]

View File

@@ -5149,3 +5149,154 @@ class deleteSystem(APIView):
except System.DoesNotExist:
return Response({'status': 'error', 'message': '系统公告不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
class ExportCaseLogExcel(APIView):
def post(self, request, *args, **kwargs):
"""
导出案件日志到Excel
必填参数case_id案件ID
可选参数start_time开始时间、end_time结束时间
返回Excel文件下载
"""
import pandas as pd
from django.http import HttpResponse
from io import BytesIO
case_id = request.data.get('case_id') # 案件ID必填
start_time = request.data.get('start_time') # 开始时间(可选)
end_time = request.data.get('end_time') # 结束时间(可选)
if not case_id:
return Response({'status': 'error', 'message': '缺少参数case_id案件ID', 'code': 1}, status=status.HTTP_400_BAD_REQUEST)
# 获取案件信息
try:
case = Case.objects.get(id=case_id, is_deleted=False)
except Case.DoesNotExist:
return Response({'status': 'error', 'message': '案件不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 构建查询条件
Q_obj = Q(is_deleted=False, case_id=case_id)
# 时间范围筛选(可选)
if start_time:
Q_obj &= Q(times__gte=start_time)
if end_time:
Q_obj &= Q(times__lte=end_time)
# 查询日志数据
logs = Caselog.objects.filter(Q_obj).order_by('-times', '-id')
if not logs.exists():
return Response({'status': 'error', 'message': '没有找到案件日志数据', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 解析案件负责人信息
responsiblefor_info = ""
if case.responsiblefor:
try:
resp_data = json.loads(case.responsiblefor) if isinstance(case.responsiblefor, str) else case.responsiblefor
if isinstance(resp_data, dict):
parts = []
if resp_data.get('responsible_person'):
parts.append(f"承办人:{resp_data.get('responsible_person')}")
if resp_data.get('main_lawyer'):
parts.append(f"主办律师:{resp_data.get('main_lawyer')}")
if resp_data.get('assist_lawyer'):
parts.append(f"协办律师:{resp_data.get('assist_lawyer')}")
if resp_data.get('trainee_lawyer'):
parts.append(f"实习律师:{resp_data.get('trainee_lawyer')}")
if resp_data.get('secretary'):
parts.append(f"秘书/助理:{resp_data.get('secretary')}")
responsiblefor_info = "".join(parts) if parts else str(case.responsiblefor)
else:
responsiblefor_info = str(case.responsiblefor)
except (json.JSONDecodeError, TypeError):
responsiblefor_info = str(case.responsiblefor) if case.responsiblefor else ""
# 获取案件标签
tags_str = ""
try:
tags = case.tags.filter(is_deleted=False).values_list('name', flat=True)
tags_str = "".join(tags) if tags else ""
except:
tags_str = ""
# 构建Excel数据
excel_data = []
for log in logs:
# 解析附件信息
file_info = ""
if log.file:
try:
files = json.loads(log.file) if isinstance(log.file, str) else log.file
if isinstance(files, list):
file_names = []
for f in files:
if isinstance(f, dict):
file_names.append(f.get('name', f.get('url', '未知文件')))
elif isinstance(f, str):
file_names.append(f)
file_info = "".join(file_names) if file_names else ""
else:
file_info = str(files)
except (json.JSONDecodeError, TypeError):
file_info = str(log.file) if log.file else ""
excel_data.append({
'日志ID': log.id,
'案件ID': case_id,
'合同编号': case.contract_no or '',
'项目类型': case.project_type or '',
'客户名称': case.client_name or '',
'相对方名称': case.party_name or '',
'项目简述': case.project_description or '',
'负责人信息': responsiblefor_info,
'收费情况': case.charge or '',
'立案时间': case.times or '',
'案件状态': case.state or '',
'案件标签': tags_str,
'已开票金额': case.invoice_status or '0',
'已收款金额': case.paymentcollection or '0',
'日志内容': log.content or '',
'记录时间': log.times or '',
'记录人': log.username or '',
'附件信息': file_info,
})
# 创建DataFrame
df = pd.DataFrame(excel_data)
# 导出Excel
output = BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df.to_excel(writer, index=False, sheet_name='案件日志')
# 调整列宽
worksheet = writer.sheets['案件日志']
for idx, col in enumerate(df.columns):
max_length = max(
df[col].astype(str).map(len).max() if len(df) > 0 else 0,
len(str(col))
)
# 限制最大列宽为50
adjusted_width = min(max_length + 2, 50)
worksheet.column_dimensions[chr(65 + idx) if idx < 26 else 'A' + chr(65 + idx - 26)].width = adjusted_width
output.seek(0)
# 生成文件名
contract_no = case.contract_no or f'案件{case_id}'
filename = f'{contract_no}_案件日志_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx'
# 返回Excel文件
response = HttpResponse(
output.read(),
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
)
# 处理中文文件名
from urllib.parse import quote
response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{quote(filename)}'
response['Access-Control-Expose-Headers'] = 'Content-Disposition'
return response