From cbefb81a350ddc1dcfbfa9d7747c19008c645f6d Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Thu, 30 Oct 2025 08:52:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E7=BB=B4=E6=8A=A4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 新增功能 ### 1. 后端API路由 (lawrisk/api/v2.py) - 添加了5个新的管理API端点: * GET /admin/regions - 获取地区列表 * GET /admin/themes - 获取主题列表(按地区筛选) * GET /admin/permits - 获取许可列表(按地区和主题筛选) * GET /admin/permit-details - 获取许可详细信息 * GET /admin/test - 测试路由 ### 2. 前端管理界面 (static/db_admin.html) - 实现了完整的数据库维护管理页面 - 4步操作流程:地区选择 → 主题列表 → 许可列表 → 详细信息展示 - 现代化UI设计,包括: * 渐变背景和响应式布局 * 平滑动画过渡效果 * 实时数据加载提示 * 完整的许可信息展示(许可状态、经营范围、法律风险等) ## 技术实现 - RESTful API设计,返回标准JSON格式 - 直接从PostgreSQL数据库读取数据 - 所有API已通过curl和Flask测试客户端验证 ## 测试结果 在端口8888上测试通过: - admin/regions: 1个地区 - admin/themes: 57个主题 - admin/permits: 6个许可 - admin/permit-details: 完整许可信息和3个风险记录 - 静态页面: 成功加载 ## 使用方法 ```bash # 启动服务 PORT=8888 python app.py & # 访问管理界面 http://localhost:8888/static/db_admin.html # API调用示例 curl http://localhost:8888/fs-ai-asistant/api/workflow/lawrisk/admin/regions ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- lawrisk/api/v2.py | 129 ++++++++- static/db_admin.html | 629 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 756 insertions(+), 2 deletions(-) create mode 100644 static/db_admin.html diff --git a/lawrisk/api/v2.py b/lawrisk/api/v2.py index 7e713da..de0a57d 100644 --- a/lawrisk/api/v2.py +++ b/lawrisk/api/v2.py @@ -6,7 +6,12 @@ from flask import Blueprint, jsonify, request from concurrent.futures import ThreadPoolExecutor from lawrisk.services.lawrisk_v2_service import search_v2, list_regions -from lawrisk.services.licensing_repo import list_permits_for_region +from lawrisk.services.licensing_repo import ( + list_permits_for_region, + load_permits_and_risks, + list_region_theme_options, + load_theme_payload, +) from lawrisk.services.lawrisk_service import suggest_questions_embed v2_bp = Blueprint('lawrisk_v2', __name__, url_prefix='/fs-ai-asistant/api/workflow/lawrisk') @@ -58,7 +63,7 @@ def lawrisk_search_v2(): return jsonify({"success": False, "message": str(e), "data": {}}), 500 -@v2_bp.get('/v2/regions') +@v2_bp.route('/v2/regions', methods=['GET']) def lawrisk_regions(): """Get list of available regions.""" try: @@ -125,3 +130,123 @@ def _extract_params(): region_value = payload.get("region") or payload.get("region_id") return query, debug_flag, top_k_int, mode_value, region_value + + +@v2_bp.route('/admin/test', methods=['GET']) +def admin_test(): + """Simple test route.""" + return jsonify({"success": True, "message": "Test route works!"}) + + +@v2_bp.route('/test-simple', methods=['GET']) +def test_simple(): + """Very simple test.""" + return jsonify({"status": "ok"}) + + +@v2_bp.route('/admin/regions', methods=['GET']) +def admin_regions(): + """Get all regions for database maintenance.""" + try: + regions = list_regions() + return jsonify({"success": True, "data": {"regions": regions}}) + except Exception as exc: + print(f"admin_regions error: {exc}") + return jsonify({"success": False, "message": str(exc)}), 500 + + +@v2_bp.route('/admin/themes', methods=['GET']) +def admin_themes(): + """Get themes for a specific region.""" + region_value = request.args.get("region") or request.args.get("region_id") + + 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) + + try: + catalog = list_region_theme_options() + region_id_lower = region_token.lower() + + themes = [] + seen_theme_ids = set() + + for item in catalog: + if (item["region_id"] == region_token or + item["region_id"].lower() == region_id_lower or + item["region_name"].lower() == region_id_lower): + theme_id = item["theme_id"] + if theme_id not in seen_theme_ids: + seen_theme_ids.add(theme_id) + themes.append({ + "id": theme_id, + "name": item["theme_name"], + "option_id": item["option_id"] + }) + + return jsonify({"success": True, "data": {"region": region_token, "themes": themes}}) + except Exception as exc: + print(f"admin_themes error: {exc}") + return jsonify({"success": False, "message": str(exc)}), 500 + + +@v2_bp.route('/admin/permits', methods=['GET']) +def admin_permits(): + """Get permits for a specific region-theme combination.""" + 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 + + 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) + + try: + permits = load_permits_and_risks(region_token, theme_token) + + return jsonify({ + "success": True, + "data": { + "region": region_token, + "theme": theme_token, + "permits": permits + } + }) + except Exception as exc: + print(f"admin_permits error: {exc}") + return jsonify({"success": False, "message": str(exc)}), 500 + + +@v2_bp.route('/admin/permit-details', methods=['GET']) +def admin_permit_details(): + """Get detailed information for a specific permit.""" + region_value = request.args.get("region") or request.args.get("region_id") + 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 + + 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) + + try: + permits = load_permits_and_risks(region_token, theme_token, permit_token) + + if not permits: + return jsonify({"success": False, "message": "Permit not found", "data": {}}), 404 + + return jsonify({ + "success": True, + "data": { + "region": region_token, + "theme": theme_token, + "permit": permits[0] + } + }) + except Exception as exc: + print(f"admin_permit_details error: {exc}") + return jsonify({"success": False, "message": str(exc)}), 500 diff --git a/static/db_admin.html b/static/db_admin.html new file mode 100644 index 0000000..d07552a --- /dev/null +++ b/static/db_admin.html @@ -0,0 +1,629 @@ + + + + + + 数据库维护页面 - LawRisk + + + +
+
+

🗃️ 数据库维护系统

+

LawRisk 法律风险提示系统 - 数据库维护与查询工具

+
+ +
+
+
1
+
选择地区
+
+
+
+
2
+
选择主题
+
+
+
+
3
+
选择许可
+
+
+
+
4
+
查看详情
+
+
+ +
+
+

选择区域

+
+
+
+
+ +
+

主题/许可详情

+
+
+ + + +

请先选择地区以查看可用主题

+
+
+
+
+
+ + + +