|
@@ -95,6 +95,92 @@ def manual_simplify(text):
|
|
|
result += mapping.get(char, char)
|
|
result += mapping.get(char, char)
|
|
|
return result
|
|
return result
|
|
|
|
|
|
|
|
|
|
+def _build_reverse_simplify_map():
|
|
|
|
|
+ """
|
|
|
|
|
+ Build a reverse map from simplified char -> list of traditional chars
|
|
|
|
|
+ based on the fallback manual_simplify mapping.
|
|
|
|
|
+ """
|
|
|
|
|
+ mapping = {
|
|
|
|
|
+ '學': '学', '國': '国', '萬': '万', '寶': '宝', '興': '兴',
|
|
|
|
|
+ '華': '华', '會': '会', '葉': '叶', '藝': '艺', '號': '号',
|
|
|
|
|
+ '處': '处', '見': '见', '視': '视', '言': '言', '語': '语',
|
|
|
|
|
+ '貝': '贝', '車': '车', '長': '长', '門': '门', '韋': '韦',
|
|
|
|
|
+ '頁': '页', '風': '风', '飛': '飞', '食': '食', '馬': '马',
|
|
|
|
|
+ '魚': '鱼', '鳥': '鸟', '麥': '麦', '黃': '黄', '齊': '齐',
|
|
|
|
|
+ '齒': '齿', '龍': '龙', '龜': '龟', '壽': '寿', '榮': '荣',
|
|
|
|
|
+ '愛': '爱', '慶': '庆', '衛': '卫', '賢': '贤', '義': '义',
|
|
|
|
|
+ '禮': '礼', '樂': '乐', '靈': '灵', '滅': '灭', '氣': '气',
|
|
|
|
|
+ '智': '智', '信': '信', '仁': '仁', '勇': '勇', '嚴': '严',
|
|
|
|
|
+ '銳': '锐', '優': '优', '楊': '杨', '吳': '吴', '銀': '银'
|
|
|
|
|
+ }
|
|
|
|
|
+ rev = {}
|
|
|
|
|
+ for trad, simp in mapping.items():
|
|
|
|
|
+ rev.setdefault(simp, [])
|
|
|
|
|
+ if trad not in rev[simp]:
|
|
|
|
|
+ rev[simp].append(trad)
|
|
|
|
|
+ return rev
|
|
|
|
|
+
|
|
|
|
|
+_REVERSE_SIMPLIFY_MAP = _build_reverse_simplify_map()
|
|
|
|
|
+
|
|
|
|
|
+def expand_name_search_variants(keyword, max_variants=60):
|
|
|
|
|
+ """
|
|
|
|
|
+ Expand keyword into a small set of variants so Simplified/Traditional
|
|
|
|
|
+ searches can match both `name` and `simplified_name`.
|
|
|
|
|
+
|
|
|
|
|
+ - Always includes original keyword
|
|
|
|
|
+ - Includes fallback-trad->simp conversion
|
|
|
|
|
+ - Includes best-effort simp->trad expansions based on reverse map
|
|
|
|
|
+ """
|
|
|
|
|
+ if not keyword:
|
|
|
|
|
+ return []
|
|
|
|
|
+ kw = str(keyword).strip()
|
|
|
|
|
+ if not kw:
|
|
|
|
|
+ return []
|
|
|
|
|
+
|
|
|
|
|
+ variants = set([kw])
|
|
|
|
|
+ variants.add(manual_simplify(kw))
|
|
|
|
|
+
|
|
|
|
|
+ # Build possible traditional variants when the input is simplified.
|
|
|
|
|
+ # For each char, if we have traditional candidates, branch; otherwise keep itself.
|
|
|
|
|
+ choices = []
|
|
|
|
|
+ for ch in kw:
|
|
|
|
|
+ cand = _REVERSE_SIMPLIFY_MAP.get(ch)
|
|
|
|
|
+ if cand:
|
|
|
|
|
+ # include itself too (covers already-traditional or neutral chars)
|
|
|
|
|
+ choices.append([ch] + cand)
|
|
|
|
|
+ else:
|
|
|
|
|
+ choices.append([ch])
|
|
|
|
|
+
|
|
|
|
|
+ # Cartesian product with early stop.
|
|
|
|
|
+ results = ['']
|
|
|
|
|
+ for opts in choices:
|
|
|
|
|
+ new_results = []
|
|
|
|
|
+ for prefix in results:
|
|
|
|
|
+ for opt in opts:
|
|
|
|
|
+ new_results.append(prefix + opt)
|
|
|
|
|
+ if len(new_results) >= max_variants:
|
|
|
|
|
+ break
|
|
|
|
|
+ if len(new_results) >= max_variants:
|
|
|
|
|
+ break
|
|
|
|
|
+ results = new_results
|
|
|
|
|
+ if len(results) >= max_variants:
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
|
|
+ for r in results:
|
|
|
|
|
+ if r:
|
|
|
|
|
+ variants.add(r)
|
|
|
|
|
+ variants.add(manual_simplify(r))
|
|
|
|
|
+
|
|
|
|
|
+ # Keep deterministic order for stable SQL params
|
|
|
|
|
+ ordered = []
|
|
|
|
|
+ for v in variants:
|
|
|
|
|
+ v2 = (v or '').strip()
|
|
|
|
|
+ if v2 and v2 not in ordered:
|
|
|
|
|
+ ordered.append(v2)
|
|
|
|
|
+ if len(ordered) >= max_variants:
|
|
|
|
|
+ break
|
|
|
|
|
+ return ordered
|
|
|
|
|
+
|
|
|
def clean_name(name):
|
|
def clean_name(name):
|
|
|
"""
|
|
"""
|
|
|
Clean name according to Liu family genealogy rules:
|
|
Clean name according to Liu family genealogy rules:
|
|
@@ -450,6 +536,66 @@ def process_ai_task(record_id, image_url):
|
|
|
conn.close()
|
|
conn.close()
|
|
|
print(f"[AI Task] Task finished for record {record_id}")
|
|
print(f"[AI Task] Task finished for record {record_id}")
|
|
|
|
|
|
|
|
|
|
+def ensure_pdf_table():
|
|
|
|
|
+ conn = get_db_connection()
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn.cursor() as cursor:
|
|
|
|
|
+ cursor.execute("""
|
|
|
|
|
+ CREATE TABLE IF NOT EXISTS genealogy_pdfs (
|
|
|
|
|
+ id INT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
+ file_name VARCHAR(255) NOT NULL,
|
|
|
|
|
+ oss_url TEXT NOT NULL,
|
|
|
|
|
+ description VARCHAR(500) DEFAULT '',
|
|
|
|
|
+ upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
+ uploader VARCHAR(100) DEFAULT ''
|
|
|
|
|
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
|
|
|
|
+ """)
|
|
|
|
|
+ conn.commit()
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn.close()
|
|
|
|
|
+
|
|
|
|
|
+@app.route('/manager/pdf_management')
|
|
|
|
|
+def pdf_management():
|
|
|
|
|
+ if 'user_id' not in session:
|
|
|
|
|
+ return redirect(url_for('login'))
|
|
|
|
|
+
|
|
|
|
|
+ ensure_pdf_table()
|
|
|
|
|
+ view_id = request.args.get('view', type=int)
|
|
|
|
|
+ selected_pdf = None
|
|
|
|
|
+
|
|
|
|
|
+ conn = get_db_connection()
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn.cursor() as cursor:
|
|
|
|
|
+ cursor.execute("SELECT * FROM genealogy_pdfs ORDER BY upload_time DESC")
|
|
|
|
|
+ pdfs = cursor.fetchall()
|
|
|
|
|
+ if view_id:
|
|
|
|
|
+ cursor.execute("SELECT * FROM genealogy_pdfs WHERE id = %s", (view_id,))
|
|
|
|
|
+ selected_pdf = cursor.fetchone()
|
|
|
|
|
+ elif pdfs:
|
|
|
|
|
+ selected_pdf = pdfs[0]
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn.close()
|
|
|
|
|
+
|
|
|
|
|
+ return render_template('pdf_management.html', pdfs=pdfs, selected_pdf=selected_pdf)
|
|
|
|
|
+
|
|
|
|
|
+@app.route('/manager/delete_pdf/<int:pdf_id>', methods=['POST'])
|
|
|
|
|
+def delete_pdf(pdf_id):
|
|
|
|
|
+ if 'user_id' not in session:
|
|
|
|
|
+ return jsonify({"success": False, "message": "Unauthorized"}), 401
|
|
|
|
|
+
|
|
|
|
|
+ conn = get_db_connection()
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn.cursor() as cursor:
|
|
|
|
|
+ cursor.execute("DELETE FROM genealogy_pdfs WHERE id = %s", (pdf_id,))
|
|
|
|
|
+ conn.commit()
|
|
|
|
|
+ flash('PDF文件记录已删除')
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ flash(f'删除失败: {e}')
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn.close()
|
|
|
|
|
+
|
|
|
|
|
+ return redirect(url_for('pdf_management'))
|
|
|
|
|
+
|
|
|
@app.route('/manager/')
|
|
@app.route('/manager/')
|
|
|
def index():
|
|
def index():
|
|
|
if 'user_id' not in session:
|
|
if 'user_id' not in session:
|
|
@@ -515,7 +661,17 @@ def members():
|
|
|
with conn.cursor() as cursor:
|
|
with conn.cursor() as cursor:
|
|
|
# 1. Get total count
|
|
# 1. Get total count
|
|
|
if search_name:
|
|
if search_name:
|
|
|
- cursor.execute("SELECT COUNT(*) as count FROM family_member_info WHERE name LIKE %s", (f"%{search_name}%",))
|
|
|
|
|
|
|
+ variants = expand_name_search_variants(search_name)
|
|
|
|
|
+ where_parts = []
|
|
|
|
|
+ params = []
|
|
|
|
|
+ for v in variants:
|
|
|
|
|
+ where_parts.append("(name LIKE %s OR simplified_name LIKE %s)")
|
|
|
|
|
+ like = f"%{v}%"
|
|
|
|
|
+ params.extend([like, like])
|
|
|
|
|
+ where_clause = " OR ".join(where_parts) if where_parts else "name LIKE %s"
|
|
|
|
|
+ if not where_parts:
|
|
|
|
|
+ params = [f"%{search_name}%"]
|
|
|
|
|
+ cursor.execute(f"SELECT COUNT(*) as count FROM family_member_info WHERE {where_clause}", tuple(params))
|
|
|
else:
|
|
else:
|
|
|
cursor.execute("SELECT COUNT(*) as count FROM family_member_info")
|
|
cursor.execute("SELECT COUNT(*) as count FROM family_member_info")
|
|
|
|
|
|
|
@@ -528,8 +684,19 @@ def members():
|
|
|
order_clause = "ORDER BY COALESCE(modified_time, create_time) DESC"
|
|
order_clause = "ORDER BY COALESCE(modified_time, create_time) DESC"
|
|
|
|
|
|
|
|
if search_name:
|
|
if search_name:
|
|
|
- sql = f"SELECT * FROM family_member_info WHERE name LIKE %s {order_clause} LIMIT %s OFFSET %s"
|
|
|
|
|
- cursor.execute(sql, (f"%{search_name}%", per_page, offset))
|
|
|
|
|
|
|
+ variants = expand_name_search_variants(search_name)
|
|
|
|
|
+ where_parts = []
|
|
|
|
|
+ params = []
|
|
|
|
|
+ for v in variants:
|
|
|
|
|
+ where_parts.append("(name LIKE %s OR simplified_name LIKE %s)")
|
|
|
|
|
+ like = f"%{v}%"
|
|
|
|
|
+ params.extend([like, like])
|
|
|
|
|
+ where_clause = " OR ".join(where_parts) if where_parts else "(name LIKE %s OR simplified_name LIKE %s)"
|
|
|
|
|
+ if not where_parts:
|
|
|
|
|
+ like = f"%{search_name}%"
|
|
|
|
|
+ params = [like, like]
|
|
|
|
|
+ sql = f"SELECT * FROM family_member_info WHERE {where_clause} {order_clause} LIMIT %s OFFSET %s"
|
|
|
|
|
+ cursor.execute(sql, tuple(params + [per_page, offset]))
|
|
|
else:
|
|
else:
|
|
|
sql = f"SELECT * FROM family_member_info {order_clause} LIMIT %s OFFSET %s"
|
|
sql = f"SELECT * FROM family_member_info {order_clause} LIMIT %s OFFSET %s"
|
|
|
cursor.execute(sql, (per_page, offset))
|
|
cursor.execute(sql, (per_page, offset))
|
|
@@ -1360,16 +1527,49 @@ def start_analysis(record_id):
|
|
|
|
|
|
|
|
def process_files_background(upload_folder, saved_files, manual_page, suggested_page, genealogy_version, genealogy_source, upload_person):
|
|
def process_files_background(upload_folder, saved_files, manual_page, suggested_page, genealogy_version, genealogy_source, upload_person):
|
|
|
current_suggested_page = int(manual_page) if manual_page and str(manual_page).isdigit() else suggested_page
|
|
current_suggested_page = int(manual_page) if manual_page and str(manual_page).isdigit() else suggested_page
|
|
|
-
|
|
|
|
|
|
|
+ ensure_pdf_table()
|
|
|
|
|
+
|
|
|
for item in saved_files:
|
|
for item in saved_files:
|
|
|
- if len(item) == 3:
|
|
|
|
|
|
|
+ if len(item) >= 4:
|
|
|
|
|
+ filename, file_path, file_page, original_filename = item[0], item[1], item[2], item[3]
|
|
|
|
|
+ elif len(item) == 3:
|
|
|
filename, file_path, file_page = item
|
|
filename, file_path, file_page = item
|
|
|
|
|
+ original_filename = filename
|
|
|
else:
|
|
else:
|
|
|
- filename, file_path = item
|
|
|
|
|
|
|
+ filename, file_path = item[0], item[1]
|
|
|
file_page = None
|
|
file_page = None
|
|
|
-
|
|
|
|
|
|
|
+ original_filename = filename
|
|
|
|
|
+
|
|
|
try:
|
|
try:
|
|
|
if filename.lower().endswith('.pdf'):
|
|
if filename.lower().endswith('.pdf'):
|
|
|
|
|
+ import uuid
|
|
|
|
|
+ display_pdf_name = (original_filename or filename).strip() or filename
|
|
|
|
|
+ oss_pdf_name = secure_filename(display_pdf_name)
|
|
|
|
|
+ if not oss_pdf_name or not oss_pdf_name.lower().endswith('.pdf'):
|
|
|
|
|
+ oss_pdf_name = f"genealogy_pdf_{uuid.uuid4().hex[:8]}.pdf"
|
|
|
|
|
+ pdf_oss_url = upload_to_oss(file_path, custom_filename=oss_pdf_name)
|
|
|
|
|
+ if pdf_oss_url:
|
|
|
|
|
+ desc_parts = []
|
|
|
|
|
+ if genealogy_version:
|
|
|
|
|
+ desc_parts.append(genealogy_version)
|
|
|
|
|
+ if genealogy_source:
|
|
|
|
|
+ desc_parts.append(genealogy_source)
|
|
|
|
|
+ pdf_description = ' · '.join(desc_parts) if desc_parts else ''
|
|
|
|
|
+ conn_pdf = get_db_connection()
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn_pdf.cursor() as cursor:
|
|
|
|
|
+ cursor.execute(
|
|
|
|
|
+ "INSERT INTO genealogy_pdfs (file_name, oss_url, description, uploader) VALUES (%s, %s, %s, %s)",
|
|
|
|
|
+ (display_pdf_name, pdf_oss_url, pdf_description, upload_person or '')
|
|
|
|
|
+ )
|
|
|
|
|
+ conn_pdf.commit()
|
|
|
|
|
+ except Exception as pdf_meta_e:
|
|
|
|
|
+ print(f"Error inserting genealogy_pdfs for {display_pdf_name}: {pdf_meta_e}")
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn_pdf.close()
|
|
|
|
|
+ else:
|
|
|
|
|
+ print(f"Warning: full PDF upload to OSS failed for {filename}, scan pages will still be processed.")
|
|
|
|
|
+
|
|
|
doc = fitz.open(file_path)
|
|
doc = fitz.open(file_path)
|
|
|
for page_index in range(len(doc)):
|
|
for page_index in range(len(doc)):
|
|
|
img_path = None
|
|
img_path = None
|
|
@@ -1533,7 +1733,7 @@ def upload():
|
|
|
|
|
|
|
|
# Fetch individual page number if it exists
|
|
# Fetch individual page number if it exists
|
|
|
file_page = request.form.get(f'page_number_{i}')
|
|
file_page = request.form.get(f'page_number_{i}')
|
|
|
- saved_files.append((filename, file_path, file_page))
|
|
|
|
|
|
|
+ saved_files.append((filename, file_path, file_page, original_filename))
|
|
|
|
|
|
|
|
if saved_files:
|
|
if saved_files:
|
|
|
threading.Thread(
|
|
threading.Thread(
|
|
@@ -1603,5 +1803,133 @@ def delete_upload(record_id):
|
|
|
finally:
|
|
finally:
|
|
|
conn.close()
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
+@app.route('/manager/upload_pdf', methods=['POST'])
|
|
|
|
|
+def upload_pdf():
|
|
|
|
|
+ if 'user_id' not in session:
|
|
|
|
|
+ return jsonify({"success": False, "message": "Unauthorized"}), 401
|
|
|
|
|
+
|
|
|
|
|
+ if 'file' not in request.files:
|
|
|
|
|
+ return jsonify({"success": False, "message": "未选择文件"}), 400
|
|
|
|
|
+
|
|
|
|
|
+ file = request.files['file']
|
|
|
|
|
+ if file.filename == '':
|
|
|
|
|
+ return jsonify({"success": False, "message": "未选择文件"}), 400
|
|
|
|
|
+
|
|
|
|
|
+ if not file.filename.lower().endswith('.pdf'):
|
|
|
|
|
+ return jsonify({"success": False, "message": "请上传PDF文件"}), 400
|
|
|
|
|
+
|
|
|
|
|
+ import uuid
|
|
|
|
|
+ original_filename = file.filename
|
|
|
|
|
+ ext = os.path.splitext(original_filename)[1].lower()
|
|
|
|
|
+ base_name = secure_filename(original_filename)
|
|
|
|
|
+
|
|
|
|
|
+ if not base_name or base_name == ext.strip('.'):
|
|
|
|
|
+ filename = f"genealogy_pdf_{uuid.uuid4().hex[:8]}{ext}"
|
|
|
|
|
+ else:
|
|
|
|
|
+ if not base_name.lower().endswith(ext):
|
|
|
|
|
+ filename = f"{base_name}{ext}"
|
|
|
|
|
+ else:
|
|
|
|
|
+ filename = base_name
|
|
|
|
|
+
|
|
|
|
|
+ file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
|
|
|
|
+ file.save(file_path)
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ # Upload to OSS
|
|
|
|
|
+ oss_url = upload_to_oss(file_path, custom_filename=filename)
|
|
|
|
|
+ if not oss_url:
|
|
|
|
|
+ return jsonify({"success": False, "message": "文件上传失败"}), 500
|
|
|
|
|
+
|
|
|
|
|
+ # Get form data
|
|
|
|
|
+ uploader = request.form.get('uploader', session.get('username', ''))
|
|
|
|
|
+ version_name = request.form.get('version_name', '')
|
|
|
|
|
+ version_source = request.form.get('version_source', '')
|
|
|
|
|
+ file_provider = request.form.get('file_provider', uploader)
|
|
|
|
|
+
|
|
|
|
|
+ # Save to database
|
|
|
|
|
+ conn = get_db_connection()
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn.cursor() as cursor:
|
|
|
|
|
+ cursor.execute(
|
|
|
|
|
+ "INSERT INTO genealogy_pdfs (file_name, oss_url, uploader, version_name, version_source, file_provider) VALUES (%s, %s, %s, %s, %s, %s)",
|
|
|
|
|
+ (original_filename, oss_url, uploader, version_name, version_source, file_provider)
|
|
|
|
|
+ )
|
|
|
|
|
+ conn.commit()
|
|
|
|
|
+
|
|
|
|
|
+ # Start background processing for PDF pages
|
|
|
|
|
+ threading.Thread(
|
|
|
|
|
+ target=process_pdf_pages,
|
|
|
|
|
+ args=(file_path, oss_url, uploader)
|
|
|
|
|
+ ).start()
|
|
|
|
|
+
|
|
|
|
|
+ return jsonify({"success": True, "message": "PDF文件上传成功,正在解析页面"})
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ return jsonify({"success": False, "message": f"保存失败: {e}"}), 500
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn.close()
|
|
|
|
|
+ finally:
|
|
|
|
|
+ if os.path.exists(file_path):
|
|
|
|
|
+ try:
|
|
|
|
|
+ os.remove(file_path)
|
|
|
|
|
+ except:
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+def process_pdf_pages(file_path, pdf_oss_url, uploader):
|
|
|
|
|
+ """Process PDF pages and add them to genealogy records"""
|
|
|
|
|
+ try:
|
|
|
|
|
+ import fitz
|
|
|
|
|
+ doc = fitz.open(file_path)
|
|
|
|
|
+
|
|
|
|
|
+ # Get current max page number
|
|
|
|
|
+ conn = get_db_connection()
|
|
|
|
|
+ suggested_page = 1
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn.cursor() as cursor:
|
|
|
|
|
+ cursor.execute("SELECT MAX(page_number) as max_p FROM genealogy_records")
|
|
|
|
|
+ result = cursor.fetchone()
|
|
|
|
|
+ if result and result['max_p']:
|
|
|
|
|
+ suggested_page = result['max_p'] + 1
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn.close()
|
|
|
|
|
+
|
|
|
|
|
+ for page_index in range(len(doc)):
|
|
|
|
|
+ try:
|
|
|
|
|
+ page = doc[page_index]
|
|
|
|
|
+ pix = page.get_pixmap(dpi=150)
|
|
|
|
|
+
|
|
|
|
|
+ # Save as image
|
|
|
|
|
+ img_filename = f"{os.path.splitext(os.path.basename(file_path))[0]}_page_{page_index+1}.jpg"
|
|
|
|
|
+ img_path = os.path.join(app.config['UPLOAD_FOLDER'], img_filename)
|
|
|
|
|
+ pix.save(img_path)
|
|
|
|
|
+
|
|
|
|
|
+ # Upload to OSS
|
|
|
|
|
+ img_oss_url = upload_to_oss(img_path, custom_filename=img_filename)
|
|
|
|
|
+ if img_oss_url:
|
|
|
|
|
+ # Save to genealogy_records
|
|
|
|
|
+ conn = get_db_connection()
|
|
|
|
|
+ try:
|
|
|
|
|
+ with conn.cursor() as cursor:
|
|
|
|
|
+ cursor.execute(
|
|
|
|
|
+ "INSERT INTO genealogy_records (file_name, oss_url, page_number, ai_status, upload_person, file_type) VALUES (%s, %s, %s, 1, %s, %s)",
|
|
|
|
|
+ (img_filename, img_oss_url, suggested_page + page_index, uploader, '图片')
|
|
|
|
|
+ )
|
|
|
|
|
+ record_id = cursor.lastrowid
|
|
|
|
|
+ conn.commit()
|
|
|
|
|
+
|
|
|
|
|
+ # Start AI processing
|
|
|
|
|
+ threading.Thread(target=process_ai_task, args=(record_id, img_oss_url)).start()
|
|
|
|
|
+ finally:
|
|
|
|
|
+ conn.close()
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ print(f"Error processing page {page_index+1}: {e}")
|
|
|
|
|
+ finally:
|
|
|
|
|
+ if 'img_path' in locals() and os.path.exists(img_path):
|
|
|
|
|
+ try:
|
|
|
|
|
+ os.remove(img_path)
|
|
|
|
|
+ except:
|
|
|
|
|
+ pass
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ print(f"Error processing PDF: {e}")
|
|
|
|
|
+
|
|
|
if __name__ == '__main__':
|
|
if __name__ == '__main__':
|
|
|
app.run(debug=False, port=5001)
|
|
app.run(debug=False, port=5001)
|