|
|
@@ -5,6 +5,7 @@ import json
|
|
|
import re
|
|
|
import threading
|
|
|
import urllib3
|
|
|
+import fitz # PyMuPDF
|
|
|
from flask import Flask, render_template, request, redirect, url_for, session, flash, jsonify, Response, stream_with_context
|
|
|
from werkzeug.utils import secure_filename
|
|
|
from oss_utils import upload_to_oss
|
|
|
@@ -22,15 +23,40 @@ os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
|
|
|
|
|
# 数据库配置
|
|
|
DB_CONFIG = {
|
|
|
- "host": "rm-f8ze60yirdj8786u2.mysql.rds.aliyuncs.com",
|
|
|
+ "host": "rm-f8ze60yirdj8786u2wo.mysql.rds.aliyuncs.com",
|
|
|
"port": 3306,
|
|
|
- "user": "root",
|
|
|
- "password": "csqz@20255",
|
|
|
+ "user": "csqz",
|
|
|
+ "password": "csqz@2026",
|
|
|
"db": "csqz-client",
|
|
|
"charset": "utf8mb4",
|
|
|
"cursorclass": pymysql.cursors.DictCursor
|
|
|
}
|
|
|
|
|
|
+from PIL import Image
|
|
|
+
|
|
|
+def compress_image_if_needed(file_path, max_dim=2000):
|
|
|
+ """Compress, resize and normalize image to JPEG for AI processing."""
|
|
|
+ try:
|
|
|
+ # We always want to normalize to JPEG so AI doesn't complain about format
|
|
|
+ with Image.open(file_path) as img:
|
|
|
+ # Convert RGBA/P or any other mode to RGB for JPEG saving
|
|
|
+ if img.mode != 'RGB':
|
|
|
+ img = img.convert('RGB')
|
|
|
+
|
|
|
+ width, height = img.size
|
|
|
+ if max(width, height) > max_dim:
|
|
|
+ ratio = max_dim / max(width, height)
|
|
|
+ new_size = (int(width * ratio), int(height * ratio))
|
|
|
+ img = img.resize(new_size, Image.Resampling.LANCZOS)
|
|
|
+
|
|
|
+ # Always save as JPEG to normalize the format
|
|
|
+ new_path = os.path.splitext(file_path)[0] + '_normalized.jpg'
|
|
|
+ img.save(new_path, 'JPEG', quality=85)
|
|
|
+ return new_path
|
|
|
+ except Exception as e:
|
|
|
+ print(f"Warning: Image compression/normalization failed for {file_path}: {e}")
|
|
|
+ return file_path
|
|
|
+
|
|
|
def get_db_connection():
|
|
|
return pymysql.connect(**DB_CONFIG)
|
|
|
|
|
|
@@ -100,6 +126,39 @@ def clean_name(name):
|
|
|
|
|
|
return name
|
|
|
|
|
|
+def get_normalized_base64_image(image_url):
|
|
|
+ """Download image, normalize to JPEG, and return base64 data URI for AI payload."""
|
|
|
+ import io
|
|
|
+ import base64
|
|
|
+ import requests
|
|
|
+ from PIL import Image
|
|
|
+
|
|
|
+ try:
|
|
|
+ response = requests.get(image_url, timeout=30)
|
|
|
+ response.raise_for_status()
|
|
|
+
|
|
|
+ with Image.open(io.BytesIO(response.content)) as img:
|
|
|
+ # Convert to RGB to ensure JPEG compatibility
|
|
|
+ if img.mode != 'RGB':
|
|
|
+ img = img.convert('RGB')
|
|
|
+
|
|
|
+ # Resize if too large
|
|
|
+ max_dim = 2000
|
|
|
+ if max(img.width, img.height) > max_dim:
|
|
|
+ ratio = max_dim / max(img.width, img.height)
|
|
|
+ new_size = (int(img.width * ratio), int(img.height * ratio))
|
|
|
+ img = img.resize(new_size, Image.Resampling.LANCZOS)
|
|
|
+
|
|
|
+ # Save as JPEG in memory
|
|
|
+ buffer = io.BytesIO()
|
|
|
+ img.save(buffer, format='JPEG', quality=85)
|
|
|
+
|
|
|
+ b64_str = base64.b64encode(buffer.getvalue()).decode('utf-8')
|
|
|
+ return f"data:image/jpeg;base64,{b64_str}"
|
|
|
+ except Exception as e:
|
|
|
+ print(f"Error normalizing image from {image_url}: {e}")
|
|
|
+ return image_url # Fallback to original URL if processing fails
|
|
|
+
|
|
|
def process_ai_task(record_id, image_url):
|
|
|
"""Background task to process image with AI and store result."""
|
|
|
print(f"[AI Task] Starting task for record {record_id}...")
|
|
|
@@ -134,6 +193,8 @@ def process_ai_task(record_id, image_url):
|
|
|
Do not output any reasoning or explanation, just the JSON.
|
|
|
"""
|
|
|
|
|
|
+ ai_payload_url = get_normalized_base64_image(image_url)
|
|
|
+
|
|
|
payload = {
|
|
|
"model": "doubao-seed-1-8-251228",
|
|
|
"stream": True, # Streaming for robust handling
|
|
|
@@ -141,7 +202,7 @@ def process_ai_task(record_id, image_url):
|
|
|
{
|
|
|
"role": "user",
|
|
|
"content": [
|
|
|
- {"type": "input_image", "image_url": image_url},
|
|
|
+ {"type": "input_image", "image_url": ai_payload_url},
|
|
|
{"type": "input_text", "text": prompt}
|
|
|
]
|
|
|
}
|
|
|
@@ -357,17 +418,51 @@ def process_ai_task(record_id, image_url):
|
|
|
def index():
|
|
|
if 'user_id' not in session:
|
|
|
return redirect(url_for('login'))
|
|
|
+
|
|
|
+ page = request.args.get('page', 1, type=int)
|
|
|
+ version = request.args.get('version', '').strip()
|
|
|
+ source = request.args.get('source', '').strip()
|
|
|
+ person = request.args.get('person', '').strip()
|
|
|
+ file_type = request.args.get('file_type', '').strip()
|
|
|
+ per_page = 10
|
|
|
+ offset = (page - 1) * per_page
|
|
|
|
|
|
conn = get_db_connection()
|
|
|
try:
|
|
|
with conn.cursor() as cursor:
|
|
|
- # 获取家谱图片记录 (上传管理)
|
|
|
- cursor.execute("SELECT * FROM genealogy_records ORDER BY upload_time DESC")
|
|
|
+ query_conditions = []
|
|
|
+ params = []
|
|
|
+ if version:
|
|
|
+ query_conditions.append("genealogy_version LIKE %s")
|
|
|
+ params.append(f"%{version}%")
|
|
|
+ if source:
|
|
|
+ query_conditions.append("genealogy_source LIKE %s")
|
|
|
+ params.append(f"%{source}%")
|
|
|
+ if person:
|
|
|
+ query_conditions.append("upload_person LIKE %s")
|
|
|
+ params.append(f"%{person}%")
|
|
|
+ if file_type:
|
|
|
+ query_conditions.append("file_type = %s")
|
|
|
+ params.append(file_type)
|
|
|
+
|
|
|
+ where_clause = ""
|
|
|
+ if query_conditions:
|
|
|
+ where_clause = "WHERE " + " AND ".join(query_conditions)
|
|
|
+
|
|
|
+ count_sql = f"SELECT COUNT(*) as count FROM genealogy_records {where_clause}"
|
|
|
+ cursor.execute(count_sql, params)
|
|
|
+ total = cursor.fetchone()['count']
|
|
|
+
|
|
|
+ sql = f"SELECT * FROM genealogy_records {where_clause} ORDER BY page_number ASC LIMIT %s OFFSET %s"
|
|
|
+ cursor.execute(sql, params + [per_page, offset])
|
|
|
records = cursor.fetchall()
|
|
|
+
|
|
|
+ total_pages = (total + per_page - 1) // per_page
|
|
|
+
|
|
|
finally:
|
|
|
conn.close()
|
|
|
|
|
|
- return render_template('index.html', records=records)
|
|
|
+ return render_template('index.html', records=records, page=page, total_pages=total_pages, version=version, source=source, person=person, file_type=file_type, total=total)
|
|
|
|
|
|
@app.route('/manager/members')
|
|
|
def members():
|
|
|
@@ -1051,6 +1146,8 @@ def recognize_image():
|
|
|
如果包含多个人物,请都提取出来。
|
|
|
"""
|
|
|
|
|
|
+ ai_payload_url = get_normalized_base64_image(image_url)
|
|
|
+
|
|
|
payload = {
|
|
|
"model": "doubao-seed-1-8-251228",
|
|
|
"stream": True,
|
|
|
@@ -1060,7 +1157,7 @@ def recognize_image():
|
|
|
"content": [
|
|
|
{
|
|
|
"type": "input_image",
|
|
|
- "image_url": image_url
|
|
|
+ "image_url": ai_payload_url
|
|
|
},
|
|
|
{
|
|
|
"type": "input_text",
|
|
|
@@ -1185,6 +1282,201 @@ def start_analysis(record_id):
|
|
|
finally:
|
|
|
conn.close()
|
|
|
|
|
|
+def process_files_background(saved_files, manual_page, suggested_page, genealogy_version, genealogy_source, upload_person):
|
|
|
+ current_suggested_page = int(manual_page) if manual_page and manual_page.isdigit() else suggested_page
|
|
|
+
|
|
|
+ for filename, file_path in saved_files:
|
|
|
+ try:
|
|
|
+ if filename.lower().endswith('.pdf'):
|
|
|
+ doc = fitz.open(file_path)
|
|
|
+ for page_index in range(len(doc)):
|
|
|
+ img_path = None
|
|
|
+ try:
|
|
|
+ page = doc.load_page(page_index)
|
|
|
+ max_dim = max(page.rect.width, page.rect.height)
|
|
|
+ zoom = 2000 / max_dim if max_dim > 0 else 2.0
|
|
|
+ if zoom > 2.5: zoom = 2.5
|
|
|
+ mat = fitz.Matrix(zoom, zoom)
|
|
|
+
|
|
|
+ pix = page.get_pixmap(matrix=mat)
|
|
|
+ img_filename = f"{os.path.splitext(filename)[0]}_page_{page_index+1}.jpg"
|
|
|
+ img_path = os.path.join(app.config['UPLOAD_FOLDER'], img_filename)
|
|
|
+ pix.save(img_path)
|
|
|
+
|
|
|
+ oss_url = upload_to_oss(img_path)
|
|
|
+ if oss_url:
|
|
|
+ final_page = current_suggested_page
|
|
|
+ conn = get_db_connection()
|
|
|
+ try:
|
|
|
+ with conn.cursor() as cursor:
|
|
|
+ sql = """INSERT INTO genealogy_records
|
|
|
+ (file_name, oss_url, page_number, ai_status, genealogy_version, genealogy_source, upload_person, file_type)
|
|
|
+ VALUES (%s, %s, %s, 1, %s, %s, %s, %s)"""
|
|
|
+ cursor.execute(sql, (img_filename, oss_url, final_page, genealogy_version, genealogy_source, upload_person, 'PDF'))
|
|
|
+ record_id = cursor.lastrowid
|
|
|
+ conn.commit()
|
|
|
+ threading.Thread(target=process_ai_task, args=(record_id, oss_url)).start()
|
|
|
+ current_suggested_page += 1
|
|
|
+ finally:
|
|
|
+ conn.close()
|
|
|
+ finally:
|
|
|
+ if img_path and os.path.exists(img_path):
|
|
|
+ try:
|
|
|
+ os.remove(img_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+ doc.close()
|
|
|
+ else:
|
|
|
+ img_path = compress_image_if_needed(file_path)
|
|
|
+
|
|
|
+ page_num = extract_page_number(img_path)
|
|
|
+ final_page = page_num if page_num else current_suggested_page
|
|
|
+
|
|
|
+ ext = os.path.splitext(img_path)[1]
|
|
|
+ if genealogy_version and genealogy_source:
|
|
|
+ if final_page is not None and str(final_page).strip() != '':
|
|
|
+ img_filename = f"{genealogy_version}_{genealogy_source}_{final_page}{ext}"
|
|
|
+ else:
|
|
|
+ img_filename = f"{genealogy_version}_{genealogy_source}{ext}"
|
|
|
+ else:
|
|
|
+ img_filename = os.path.basename(img_path)
|
|
|
+
|
|
|
+ oss_url = upload_to_oss(img_path, custom_filename=img_filename)
|
|
|
+ if oss_url:
|
|
|
+ conn = get_db_connection()
|
|
|
+ try:
|
|
|
+ with conn.cursor() as cursor:
|
|
|
+ sql = """INSERT INTO genealogy_records
|
|
|
+ (file_name, oss_url, page_number, ai_status, genealogy_version, genealogy_source, upload_person, file_type)
|
|
|
+ VALUES (%s, %s, %s, 1, %s, %s, %s, %s)"""
|
|
|
+ cursor.execute(sql, (img_filename, oss_url, final_page, genealogy_version, genealogy_source, upload_person, '图片'))
|
|
|
+ record_id = cursor.lastrowid
|
|
|
+ conn.commit()
|
|
|
+ threading.Thread(target=process_ai_task, args=(record_id, oss_url)).start()
|
|
|
+ if page_num:
|
|
|
+ current_suggested_page = page_num + 1
|
|
|
+ else:
|
|
|
+ current_suggested_page += 1
|
|
|
+ finally:
|
|
|
+ conn.close()
|
|
|
+ if img_path != file_path and os.path.exists(img_path):
|
|
|
+ try:
|
|
|
+ os.remove(img_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+ except Exception as e:
|
|
|
+ print(f"Error processing file {filename}: {e}")
|
|
|
+ finally:
|
|
|
+ if os.path.exists(file_path):
|
|
|
+ try:
|
|
|
+ os.remove(file_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+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
|
|
|
+
|
|
|
+ for filename, file_path in saved_files:
|
|
|
+ try:
|
|
|
+ if filename.lower().endswith('.pdf'):
|
|
|
+ doc = fitz.open(file_path)
|
|
|
+ for page_index in range(len(doc)):
|
|
|
+ img_path = None
|
|
|
+ try:
|
|
|
+ page = doc.load_page(page_index)
|
|
|
+ max_dim = max(page.rect.width, page.rect.height)
|
|
|
+ zoom = 2000 / max_dim if max_dim > 0 else 2.0
|
|
|
+ if zoom > 2.5: zoom = 2.5
|
|
|
+ mat = fitz.Matrix(zoom, zoom)
|
|
|
+
|
|
|
+ # Use get_pixmap with matrix directly
|
|
|
+ pix = page.get_pixmap(matrix=mat)
|
|
|
+
|
|
|
+ final_page = current_suggested_page
|
|
|
+ if genealogy_version and genealogy_source:
|
|
|
+ if final_page is not None and str(final_page).strip() != '':
|
|
|
+ img_filename = f"{genealogy_version}_{genealogy_source}_{final_page}.jpg"
|
|
|
+ else:
|
|
|
+ img_filename = f"{genealogy_version}_{genealogy_source}.jpg"
|
|
|
+ else:
|
|
|
+ img_filename = f"{os.path.splitext(filename)[0]}_page_{page_index+1}.jpg"
|
|
|
+
|
|
|
+ img_path = os.path.join(upload_folder, img_filename)
|
|
|
+
|
|
|
+ # Save the pixmap to the image path
|
|
|
+ pix.save(img_path)
|
|
|
+
|
|
|
+ oss_url = upload_to_oss(img_path, custom_filename=img_filename)
|
|
|
+ if oss_url:
|
|
|
+ conn = get_db_connection()
|
|
|
+ try:
|
|
|
+ with conn.cursor() as cursor:
|
|
|
+ sql = """INSERT INTO genealogy_records
|
|
|
+ (file_name, oss_url, page_number, ai_status, genealogy_version, genealogy_source, upload_person, file_type)
|
|
|
+ VALUES (%s, %s, %s, 1, %s, %s, %s, %s)"""
|
|
|
+ cursor.execute(sql, (img_filename, oss_url, final_page, genealogy_version, genealogy_source, upload_person, 'PDF'))
|
|
|
+ record_id = cursor.lastrowid
|
|
|
+ conn.commit()
|
|
|
+ threading.Thread(target=process_ai_task, args=(record_id, oss_url)).start()
|
|
|
+ current_suggested_page += 1
|
|
|
+ finally:
|
|
|
+ conn.close()
|
|
|
+ except Exception as page_e:
|
|
|
+ print(f"Error processing page {page_index} of {filename}: {page_e}")
|
|
|
+ finally:
|
|
|
+ if img_path and os.path.exists(img_path):
|
|
|
+ try:
|
|
|
+ os.remove(img_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+ doc.close()
|
|
|
+ else:
|
|
|
+ img_path = compress_image_if_needed(file_path)
|
|
|
+
|
|
|
+ page_num = extract_page_number(img_path)
|
|
|
+ final_page = page_num if page_num else current_suggested_page
|
|
|
+
|
|
|
+ ext = os.path.splitext(img_path)[1]
|
|
|
+ if genealogy_version and genealogy_source:
|
|
|
+ if final_page is not None and str(final_page).strip() != '':
|
|
|
+ img_filename = f"{genealogy_version}_{genealogy_source}_{final_page}{ext}"
|
|
|
+ else:
|
|
|
+ img_filename = f"{genealogy_version}_{genealogy_source}{ext}"
|
|
|
+ else:
|
|
|
+ img_filename = os.path.basename(img_path)
|
|
|
+
|
|
|
+ oss_url = upload_to_oss(img_path, custom_filename=img_filename)
|
|
|
+ if oss_url:
|
|
|
+ conn = get_db_connection()
|
|
|
+ try:
|
|
|
+ with conn.cursor() as cursor:
|
|
|
+ sql = """INSERT INTO genealogy_records
|
|
|
+ (file_name, oss_url, page_number, ai_status, genealogy_version, genealogy_source, upload_person, file_type)
|
|
|
+ VALUES (%s, %s, %s, 1, %s, %s, %s, %s)"""
|
|
|
+ cursor.execute(sql, (img_filename, oss_url, final_page, genealogy_version, genealogy_source, upload_person, '图片'))
|
|
|
+ record_id = cursor.lastrowid
|
|
|
+ conn.commit()
|
|
|
+ threading.Thread(target=process_ai_task, args=(record_id, oss_url)).start()
|
|
|
+ if page_num:
|
|
|
+ current_suggested_page = page_num + 1
|
|
|
+ else:
|
|
|
+ current_suggested_page += 1
|
|
|
+ finally:
|
|
|
+ conn.close()
|
|
|
+ if img_path and img_path != file_path and os.path.exists(img_path):
|
|
|
+ try:
|
|
|
+ os.remove(img_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+ except Exception as e:
|
|
|
+ print(f"Error processing file {filename}: {e}")
|
|
|
+ finally:
|
|
|
+ if os.path.exists(file_path):
|
|
|
+ try:
|
|
|
+ os.remove(file_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
@app.route('/manager/upload', methods=['GET', 'POST'])
|
|
|
def upload():
|
|
|
if 'user_id' not in session:
|
|
|
@@ -1207,60 +1499,51 @@ def upload():
|
|
|
flash('未选择文件')
|
|
|
return redirect(request.url)
|
|
|
|
|
|
- file = request.files['file']
|
|
|
- if file.filename == '':
|
|
|
+ files = request.files.getlist('file')
|
|
|
+ if not files or files[0].filename == '':
|
|
|
flash('未选择文件')
|
|
|
return redirect(request.url)
|
|
|
|
|
|
- # 允许用户在上传时直接指定页码,或者由 OCR 识别
|
|
|
manual_page = request.form.get('manual_page')
|
|
|
-
|
|
|
- if file:
|
|
|
- filename = secure_filename(file.filename)
|
|
|
- file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
|
|
- file.save(file_path)
|
|
|
+ genealogy_version = request.form.get('genealogy_version', '')
|
|
|
+ genealogy_source = request.form.get('genealogy_source', '')
|
|
|
+ upload_person = request.form.get('upload_person', '')
|
|
|
+ if not upload_person:
|
|
|
+ upload_person = session.get('username', '')
|
|
|
|
|
|
- # 1. 尝试 OCR 提取页码
|
|
|
- page_num = extract_page_number(file_path)
|
|
|
+ import uuid
|
|
|
+ saved_files = []
|
|
|
+ for file in files:
|
|
|
+ if not file or not file.filename:
|
|
|
+ continue
|
|
|
|
|
|
- # 如果 OCR 没识别到,且用户也没手动输入,则跳转到“补录页码”页面
|
|
|
- if not page_num and not manual_page:
|
|
|
- # 先把文件传到 OSS,拿到 URL,方便后续补录
|
|
|
- oss_url = upload_to_oss(file_path)
|
|
|
- if oss_url:
|
|
|
- # 暂时存入 session 或者跳转带参数
|
|
|
- return render_template('confirm_page.html',
|
|
|
- filename=filename,
|
|
|
- oss_url=oss_url,
|
|
|
- suggested_page=suggested_page)
|
|
|
- else:
|
|
|
- flash('上传 OSS 失败')
|
|
|
- return redirect(url_for('upload'))
|
|
|
-
|
|
|
- # 使用识别到的或手动输入的页码
|
|
|
- final_page = manual_page if manual_page else page_num
|
|
|
- oss_url = upload_to_oss(file_path)
|
|
|
+ original_filename = file.filename
|
|
|
+ ext = os.path.splitext(original_filename)[1].lower()
|
|
|
+ base_name = secure_filename(original_filename)
|
|
|
|
|
|
- if oss_url:
|
|
|
- conn = get_db_connection()
|
|
|
- try:
|
|
|
- with conn.cursor() as cursor:
|
|
|
- sql = "INSERT INTO genealogy_records (file_name, oss_url, page_number, ai_status) VALUES (%s, %s, %s, 1)"
|
|
|
- cursor.execute(sql, (filename, oss_url, final_page))
|
|
|
- record_id = cursor.lastrowid
|
|
|
- conn.commit()
|
|
|
-
|
|
|
- # Start AI Task
|
|
|
- threading.Thread(target=process_ai_task, args=(record_id, oss_url)).start()
|
|
|
-
|
|
|
- flash(f'上传成功!页码:{final_page},已加入解析队列')
|
|
|
- except Exception as e:
|
|
|
- flash(f'数据库错误:{e}')
|
|
|
- finally:
|
|
|
- conn.close()
|
|
|
- return redirect(url_for('index'))
|
|
|
+ # If secure_filename removes all characters (e.g., pure Chinese name) or just leaves 'pdf'
|
|
|
+ if not base_name or base_name == ext.strip('.'):
|
|
|
+ filename = f"upload_{uuid.uuid4().hex[:8]}{ext}"
|
|
|
else:
|
|
|
- flash('上传 OSS 失败')
|
|
|
+ # Ensure the extension is preserved
|
|
|
+ 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)
|
|
|
+ saved_files.append((filename, file_path))
|
|
|
+
|
|
|
+ if saved_files:
|
|
|
+ threading.Thread(
|
|
|
+ target=process_files_background,
|
|
|
+ args=(app.config['UPLOAD_FOLDER'], saved_files, manual_page, suggested_page, genealogy_version, genealogy_source, upload_person)
|
|
|
+ ).start()
|
|
|
+ flash('上传完成,AI解析中,稍后查看')
|
|
|
+
|
|
|
+ time.sleep(1.5)
|
|
|
+ return redirect(url_for('index'))
|
|
|
|
|
|
return render_template('upload.html', suggested_page=suggested_page)
|
|
|
|
|
|
@@ -1271,6 +1554,10 @@ def save_upload():
|
|
|
filename = request.form.get('filename')
|
|
|
oss_url = request.form.get('oss_url')
|
|
|
page_number = request.form.get('page_number')
|
|
|
+ genealogy_version = request.form.get('genealogy_version', '')
|
|
|
+ genealogy_source = request.form.get('genealogy_source', '')
|
|
|
+ upload_person = request.form.get('upload_person', session.get('username', ''))
|
|
|
+ file_type = request.form.get('file_type', '图片')
|
|
|
|
|
|
if not oss_url or not page_number:
|
|
|
flash('页码不能为空')
|
|
|
@@ -1279,15 +1566,17 @@ def save_upload():
|
|
|
conn = get_db_connection()
|
|
|
try:
|
|
|
with conn.cursor() as cursor:
|
|
|
- sql = "INSERT INTO genealogy_records (file_name, oss_url, page_number, ai_status) VALUES (%s, %s, %s, 1)"
|
|
|
- cursor.execute(sql, (filename, oss_url, page_number))
|
|
|
+ sql = """INSERT INTO genealogy_records
|
|
|
+ (file_name, oss_url, page_number, ai_status, genealogy_version, genealogy_source, upload_person, file_type)
|
|
|
+ VALUES (%s, %s, %s, 1, %s, %s, %s, %s)"""
|
|
|
+ cursor.execute(sql, (filename, oss_url, page_number, genealogy_version, genealogy_source, upload_person, file_type))
|
|
|
record_id = cursor.lastrowid
|
|
|
conn.commit()
|
|
|
|
|
|
# Start AI Task
|
|
|
threading.Thread(target=process_ai_task, args=(record_id, oss_url)).start()
|
|
|
|
|
|
- flash(f'记录已保存,页码:{page_number},已加入解析队列')
|
|
|
+ flash('上传完成,AI解析中,稍后查看')
|
|
|
except Exception as e:
|
|
|
flash(f'保存失败: {e}')
|
|
|
finally:
|