feat: redesign db admin import flow
This commit is contained in:
parent
fd82b757fe
commit
66cc871e47
|
|
@ -6,7 +6,7 @@ import time
|
|||
from io import BytesIO
|
||||
from flask import Blueprint, jsonify, request, send_file
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Any, Dict
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from lawrisk.api.auth import login_required, get_current_user
|
||||
from lawrisk.services.lawrisk_v2_service import search_v2, list_regions
|
||||
|
|
@ -14,6 +14,7 @@ from lawrisk.services.licensing_repo import (
|
|||
list_permits_for_region,
|
||||
load_permits_and_risks,
|
||||
list_region_theme_options,
|
||||
list_region_permit_catalog,
|
||||
load_theme_payload,
|
||||
create_checkpoint,
|
||||
list_checkpoints,
|
||||
|
|
@ -26,6 +27,8 @@ from lawrisk.services.licensing_repo import (
|
|||
start_permit_import_session,
|
||||
commit_permit_import_session,
|
||||
fetch_permit_file,
|
||||
describe_permit_import_session,
|
||||
resolve_region_permit_theme,
|
||||
)
|
||||
from lawrisk.services.lawrisk_service import suggest_questions_embed
|
||||
|
||||
|
|
@ -220,27 +223,35 @@ def admin_themes():
|
|||
|
||||
@v2_bp.route('/admin/permits', methods=['GET'])
|
||||
def admin_permits():
|
||||
"""Get permits for a specific region-theme combination."""
|
||||
"""Get permits for a region. Optional theme filter keeps backward compatibility."""
|
||||
region_value = request.args.get("region") or request.args.get("region_id")
|
||||
theme_value = request.args.get("theme") or request.args.get("theme_id")
|
||||
|
||||
if not region_value or not theme_value:
|
||||
return jsonify({"success": False, "message": "region and theme are required", "data": {}}), 400
|
||||
if not region_value or (isinstance(region_value, str) and not region_value.strip()):
|
||||
return jsonify({"success": False, "message": "region is required", "data": {}}), 400
|
||||
|
||||
region_token = region_value.strip() if isinstance(region_value, str) else str(region_value)
|
||||
theme_token = theme_value.strip() if isinstance(theme_value, str) else str(theme_value)
|
||||
theme_token = (
|
||||
theme_value.strip()
|
||||
if theme_value and isinstance(theme_value, str)
|
||||
else (str(theme_value) if theme_value is not None else None)
|
||||
)
|
||||
|
||||
try:
|
||||
if theme_token:
|
||||
permits = load_permits_and_risks(region_token, theme_token)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
data = {
|
||||
"region": region_token,
|
||||
"theme": theme_token,
|
||||
"permits": permits
|
||||
"permits": permits,
|
||||
}
|
||||
})
|
||||
else:
|
||||
catalog = list_region_permit_catalog(region_token)
|
||||
data = {
|
||||
"region": region_token,
|
||||
"permits": catalog,
|
||||
}
|
||||
return jsonify({"success": True, "data": data})
|
||||
except Exception as exc:
|
||||
print(f"admin_permits error: {exc}")
|
||||
return jsonify({"success": False, "message": str(exc)}), 500
|
||||
|
|
@ -297,6 +308,35 @@ def admin_permit_import_template():
|
|||
return jsonify({"success": False, "message": "模板文件暂时无法下载"}), 500
|
||||
|
||||
|
||||
def _build_import_preview_response(session_token: str):
|
||||
"""Internal helper to build preview response JSON."""
|
||||
try:
|
||||
data = describe_permit_import_session(session_token)
|
||||
return jsonify({"success": True, "data": data})
|
||||
except ValueError as exc:
|
||||
return jsonify({"success": False, "message": str(exc)}), 400
|
||||
except Exception as exc:
|
||||
print(f"admin_permit_import_preview error: {exc}")
|
||||
return jsonify({"success": False, "message": "无法加载预览数据"}), 500
|
||||
|
||||
|
||||
@v2_bp.route('/admin/permit-import/session/<session_id>/preview', methods=['GET'])
|
||||
def admin_permit_import_preview(session_id: str):
|
||||
"""Return parsed workbook preview along with theme options (path param)."""
|
||||
if not session_id:
|
||||
return jsonify({"success": False, "message": "session_id 不能为空"}), 400
|
||||
return _build_import_preview_response(session_id)
|
||||
|
||||
|
||||
@v2_bp.route('/admin/permit-import/preview', methods=['GET'])
|
||||
def admin_permit_import_preview_query():
|
||||
"""Return preview via query string for compatibility."""
|
||||
session_id = request.args.get("session_id") or request.args.get("sessionId")
|
||||
if not session_id:
|
||||
return jsonify({"success": False, "message": "session_id 不能为空"}), 400
|
||||
return _build_import_preview_response(session_id)
|
||||
|
||||
|
||||
@v2_bp.route('/admin/permit-import/commit', methods=['POST'])
|
||||
def admin_permit_import_commit():
|
||||
"""Commit an import session with selected sheets."""
|
||||
|
|
@ -306,6 +346,7 @@ def admin_permit_import_commit():
|
|||
overrides = payload.get('overrides') or {}
|
||||
edited_by = payload.get('edited_by') or payload.get('editedBy')
|
||||
change_summary = payload.get('change_summary') or payload.get('changeSummary')
|
||||
theme_bindings = payload.get('theme_bindings') or payload.get('themeBindings') or {}
|
||||
|
||||
if isinstance(sheet_names, str):
|
||||
sheet_names = [sheet_names]
|
||||
|
|
@ -317,6 +358,7 @@ def admin_permit_import_commit():
|
|||
overrides=overrides,
|
||||
edited_by=edited_by,
|
||||
change_summary=change_summary,
|
||||
theme_bindings=theme_bindings,
|
||||
)
|
||||
return jsonify({"success": True, "data": data})
|
||||
except ValueError as exc:
|
||||
|
|
@ -366,27 +408,58 @@ def admin_permit_details():
|
|||
theme_value = request.args.get("theme") or request.args.get("theme_id")
|
||||
permit_value = request.args.get("permit") or request.args.get("permit_id")
|
||||
|
||||
if not region_value or not theme_value or not permit_value:
|
||||
return jsonify({"success": False, "message": "region, theme, and permit are required", "data": {}}), 400
|
||||
if not region_value or not permit_value:
|
||||
return jsonify({"success": False, "message": "region and permit are required", "data": {}}), 400
|
||||
|
||||
region_token = region_value.strip() if isinstance(region_value, str) else str(region_value)
|
||||
theme_token = theme_value.strip() if isinstance(theme_value, str) else str(theme_value)
|
||||
permit_token = permit_value.strip() if isinstance(permit_value, str) else str(permit_value)
|
||||
theme_token: Optional[str]
|
||||
theme_display = None
|
||||
if theme_value is None or (isinstance(theme_value, str) and not theme_value.strip()):
|
||||
resolved = resolve_region_permit_theme(region_token, permit_token)
|
||||
if not resolved or not resolved.get("id"):
|
||||
return jsonify({"success": False, "message": "未找到许可所属主题", "data": {}}), 404
|
||||
theme_token = resolved["id"]
|
||||
theme_display = resolved
|
||||
else:
|
||||
theme_token = theme_value.strip() if isinstance(theme_value, str) else str(theme_value)
|
||||
|
||||
try:
|
||||
permits = load_permits_and_risks(region_token, theme_token, permit_token)
|
||||
# 始终加载全部主题,详情页需要展示主题列表并高亮当前主题
|
||||
permits = load_permits_and_risks(region_token, None, permit_token)
|
||||
|
||||
if not permits:
|
||||
return jsonify({"success": False, "message": "Permit not found", "data": {}}), 404
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
permit_payload = permits[0]
|
||||
payload = {
|
||||
"region": region_token,
|
||||
"theme": theme_token,
|
||||
"permit": permits[0]
|
||||
"permit": permit_payload,
|
||||
}
|
||||
})
|
||||
|
||||
selected_theme_meta = None
|
||||
theme_list = permit_payload.get("themes") or []
|
||||
if theme_token:
|
||||
for candidate in theme_list:
|
||||
if candidate.get("id") == theme_token:
|
||||
selected_theme_meta = candidate
|
||||
break
|
||||
if not selected_theme_meta and theme_display:
|
||||
selected_theme_meta = theme_display
|
||||
if not selected_theme_meta:
|
||||
selected_theme_meta = permit_payload.get("theme")
|
||||
if not selected_theme_meta and theme_list:
|
||||
selected_theme_meta = theme_list[0]
|
||||
|
||||
if selected_theme_meta:
|
||||
permit_payload["theme"] = selected_theme_meta
|
||||
payload["theme_display"] = selected_theme_meta
|
||||
payload["selected_theme_id"] = selected_theme_meta.get("id") or ""
|
||||
elif theme_display:
|
||||
payload["theme_display"] = theme_display
|
||||
|
||||
return jsonify({"success": True, "data": payload})
|
||||
except Exception as exc:
|
||||
print(f"admin_permit_details error: {exc}")
|
||||
return jsonify({"success": False, "message": str(exc)}), 500
|
||||
|
|
@ -426,12 +499,18 @@ def admin_delete_permit():
|
|||
if not change_summary:
|
||||
change_summary = None
|
||||
|
||||
if not region_value or not theme_value or not permit_value:
|
||||
return jsonify({"success": False, "message": "region_id, theme_id, permit_id 均为必填"}), 400
|
||||
if not region_value or not permit_value:
|
||||
return jsonify({"success": False, "message": "region_id 和 permit_id 均为必填"}), 400
|
||||
|
||||
region_id = region_value.strip() if isinstance(region_value, str) else str(region_value)
|
||||
theme_id = theme_value.strip() if isinstance(theme_value, str) else str(theme_value)
|
||||
permit_id = permit_value.strip() if isinstance(permit_value, str) else str(permit_value)
|
||||
if theme_value:
|
||||
theme_id = theme_value.strip() if isinstance(theme_value, str) else str(theme_value)
|
||||
else:
|
||||
resolved_theme = resolve_region_permit_theme(region_id, permit_id)
|
||||
if not resolved_theme or not resolved_theme.get("id"):
|
||||
return jsonify({"success": False, "message": "未找到许可所属主题,无法删除"}), 400
|
||||
theme_id = resolved_theme["id"]
|
||||
|
||||
try:
|
||||
result = delete_region_permit(
|
||||
|
|
|
|||
1091
static/db_admin.html
1091
static/db_admin.html
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue