From 196c8ecc7cdc234f66b9659d040be6cfceaa2549 Mon Sep 17 00:00:00 2001 From: jingrow Date: Sun, 26 Oct 2025 23:50:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A0hooks.py=E6=96=87=E4=BB=B6=E7=9A=84?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=8C=85=E4=BD=9C=E4=B8=BA=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8C=85=E5=AE=89=E8=A3=85=E5=88=B0jingrow=E9=87=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jingrow/api/local_app_installer.py | 6 +- apps/jingrow/jingrow/utils/app_installer.py | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/apps/jingrow/jingrow/api/local_app_installer.py b/apps/jingrow/jingrow/api/local_app_installer.py index 205b5b2..3942bda 100644 --- a/apps/jingrow/jingrow/api/local_app_installer.py +++ b/apps/jingrow/jingrow/api/local_app_installer.py @@ -115,7 +115,11 @@ async def install_app_from_upload( backend_result = result.get('backend_result', {}) app_dir = backend_result.get('app_dir') - # 对齐扫描安装的执行链 + # 判断是否为扩展包安装(没有 app_dir 说明是扩展包) + if not app_dir: + return result + + # 对齐扫描安装的执行链 - 只针对独立应用安装 try: # 1. 添加到 Local Installed Apps PageType from jingrow.utils.jingrow_api import get_single_pagetype diff --git a/apps/jingrow/jingrow/utils/app_installer.py b/apps/jingrow/jingrow/utils/app_installer.py index 223ccbf..3cea049 100644 --- a/apps/jingrow/jingrow/utils/app_installer.py +++ b/apps/jingrow/jingrow/utils/app_installer.py @@ -216,6 +216,64 @@ def cleanup_temp_dir(temp_dir: str): pass +@handle_errors +def install_package(temp_dir: str, package_info: Dict[str, Any]) -> Dict[str, Any]: + """将扩展包直接复制到 jingrow 应用内部并同步到数据库""" + root_dir = package_info.get('root_dir', temp_dir) + + # 获取 jingrow 应用目录 + apps_dir, _ = get_app_directories() + jingrow_backend_dir = apps_dir / "jingrow" / "jingrow" + + if not jingrow_backend_dir.exists(): + return {'success': False, 'error': '找不到 jingrow 应用目录'} + + # 检查是否有 app_name 子目录 + app_name = package_info.get('app_name') + inner_app_dir = os.path.join(root_dir, app_name) + + # 先同步到数据库(使用原始解压目录的完整文件) + try: + from jingrow.utils.jingrow_api import get_jingrow_api_headers + from jingrow.config import Config + import requests + + # 使用原始解压目录而不是复制后的目录 + sync_path = inner_app_dir if os.path.exists(inner_app_dir) and os.path.isdir(inner_app_dir) else root_dir + + api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.sync_app_files" + response = requests.post( + api_url, + json={'app_name': app_name, 'app_path': sync_path, 'force': True}, + headers=get_jingrow_api_headers(), + timeout=60 + ) + + if response.status_code != 200: + return {'success': False, 'error': f'同步到数据库失败: HTTP {response.status_code}'} + except Exception as e: + return {'success': False, 'error': f'同步到数据库失败: {str(e)}'} + + # 再复制文件到 jingrow(只复制模块目录,跳过配置和文档文件) + source_dir = inner_app_dir if os.path.exists(inner_app_dir) and os.path.isdir(inner_app_dir) else root_dir + + for item in os.listdir(source_dir): + if item in ['__pycache__', '.git', 'frontend'] or item.endswith('.json') or item in ['LICENSE.md', 'README.md', 'README']: + continue + + src = os.path.join(source_dir, item) + dst = jingrow_backend_dir / item + + if os.path.isdir(src): + if dst.exists(): + shutil.rmtree(dst) + shutil.copytree(src, dst) + else: + shutil.copy2(src, dst) + + return {'success': True, 'message': '扩展包已安装到 jingrow 应用', 'app_name': app_name} + + def is_app_installed(app_name: str) -> bool: """检查应用是否已安装""" apps_dir, _ = get_app_directories() @@ -294,6 +352,15 @@ def install_app(uploaded_file_path: str, app_name: str = None) -> Dict[str, Any] package_info = analyze_result['data'] + # 检查是否有 hooks.py + has_hooks = package_info.get('has_hooks', False) + + if not has_hooks: + # 作为扩展包安装到 jingrow 应用内部 + result = install_package(temp_dir, package_info) + cleanup_temp_dir(temp_dir) + return result + # 确定应用名称 if not app_name: app_name = package_info.get('app_name')