File size: 6,353 Bytes
b4f2238 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | """
文档处理工具Admin
独立的Admin模块
"""
from __future__ import annotations
from typing import Any
from django import forms
from django.contrib import admin
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.middleware.csrf import get_token
from django.urls import path, reverse
from apps.automation.models import AutomationTool
from apps.automation.services.document.document_processing import process_uploaded_document
class DocumentProcessorForm(forms.Form):
"""文档处理工具表单"""
upload = forms.FileField(required=True, help_text="支持PDF、DOCX和图片文件(JPG、PNG、BMP、TIFF等)")
limit = forms.IntegerField(required=False, help_text="文字提取限制(留空使用默认值1500字)")
preview_page = forms.IntegerField(required=False, min_value=1, help_text="PDF预览页码(留空使用默认值第1页)")
# @admin.register(AutomationTool) # 隐藏文档处理模块,不在Django后台显示
class DocumentProcessorAdmin(admin.ModelAdmin[AutomationTool]):
"""文档处理工具管理类"""
change_list_template = None
def get_urls(self) -> list[Any]:
urls = super().get_urls()
info = self.model._meta.app_label, self.model._meta.model_name
custom: list[Any] = [
path(
"process-document/",
self.admin_site.admin_view(self.process_view),
name="{}_{}_process_document".format(*info),
),
path("", self.admin_site.admin_view(self.redirect_to_process)),
]
return custom + urls
def redirect_to_process(self, request: HttpRequest) -> HttpResponseRedirect:
info = self.model._meta.app_label, self.model._meta.model_name
return HttpResponseRedirect(reverse("admin:{}_{}_process_document".format(*info)))
def process_view(self, request: HttpRequest) -> HttpResponse:
"""文档处理主视图"""
if request.method == "POST":
form = DocumentProcessorForm(request.POST, request.FILES)
if form.is_valid():
fp = form.cleaned_data["upload"]
limit = form.cleaned_data.get("limit")
preview_page = form.cleaned_data.get("preview_page")
try:
extraction = process_uploaded_document(fp, limit=limit, preview_page=preview_page)
except ValueError as e:
return HttpResponse(str(e))
# 构建响应信息
file_info = f"<p><strong>文件类型:</strong> {extraction.kind.upper()}</p>"
file_info += f"<p><strong>文件路径:</strong> {extraction.file_path}</p>"
if extraction.text:
html = f"""
<h1>文档处理(文件预览/文本抽取)</h1>
{file_info}
<h2>📝 提取的文本内容</h2>
<div style='background:#f8f9fa;padding:15px;border:1px solid #dee2e6;border-radius:5px;'>
<pre style='white-space:pre-wrap;margin:0;font-family:monospace;'>{extraction.text}</pre>
</div>
<p><strong>文本长度:</strong> {len(extraction.text)} 字符</p>
<p><a href='javascript:history.back()'>← 返回</a></p>
"""
return HttpResponse(html)
elif extraction.image_url:
html = f"""
<h1>文档处理(文件预览/文本抽取)</h1>
{file_info}
<h2>🖼️ 预览图(无法提取文本)</h2>
<p><em>该文件无法直接提取文字内容,已生成预览图供查看:</em></p>
<div style='text-align:center;background:#f8f9fa;padding:15px;
border:1px solid #dee2e6;border-radius:5px;'>
<img src='{extraction.image_url}'
style='max-width:100%;max-height:600px;border:1px solid #ddd;'/>
</div>
<p><a href='javascript:history.back()'>← 返回</a></p>
"""
return HttpResponse(html)
else:
html = f"""
<h1>文档处理(文件预览/文本抽取)</h1>
{file_info}
<h2>❌ 处理结果</h2>
<p style='color:orange;'>未提取到可展示的内容。可能的原因:</p>
<ul>
<li>文件为空或损坏</li>
<li>图片内容无法识别(如:纯图片、手写文字等)</li>
<li>PDF文件加密或权限限制</li>
</ul>
<p><a href='javascript:history.back()'>← 返回重新上传</a></p>
"""
return HttpResponse(html)
else:
form = DocumentProcessorForm()
csrf_token = get_token(request)
html = f"""
<h1>文档处理(文件预览/文本抽取)</h1>
<form method='post' enctype='multipart/form-data'>
<input type='hidden' name='csrfmiddlewaretoken' value='{csrf_token}' />
<p><label>上传文件:</label><br/><input type='file' name='upload' required/></p>
<p><label>文字提取限制:</label><br/><input type='number' name='limit'
placeholder='留空使用默认值1500字' min='1'/></p>
<p><label>PDF预览页码:</label><br/><input type='number' name='preview_page'
placeholder='留空使用默认值第1页' min='1'/></p>
<p><button type='submit' class='default'>提交处理</button></p>
</form>
"""
return HttpResponse(html)
def has_add_permission(self, request: HttpRequest) -> bool:
return False
def has_change_permission(self, request: HttpRequest, obj: AutomationTool | None = None) -> bool:
return True
def has_view_permission(self, request: HttpRequest, obj: AutomationTool | None = None) -> bool:
return False
def has_delete_permission(self, request: HttpRequest, obj: AutomationTool | None = None) -> bool:
return False
|