diff --git a/apps/jingrow/frontend/src/app/router/index.ts b/apps/jingrow/frontend/src/app/router/index.ts index 78bcec6..e226c19 100644 --- a/apps/jingrow/frontend/src/app/router/index.ts +++ b/apps/jingrow/frontend/src/app/router/index.ts @@ -18,6 +18,12 @@ const router = createRouter({ }, { path: '/', + name: 'HomePage', + component: () => import('../../views/HomePage.vue'), + meta: { requiresAuth: false } + }, + { + path: '/app', name: 'AppLayout', component: () => import('../layouts/AppLayout.vue'), meta: { requiresAuth: true }, diff --git a/apps/jingrow/frontend/src/locales/zh-CN.json b/apps/jingrow/frontend/src/locales/zh-CN.json index 7724eea..50b8a72 100644 --- a/apps/jingrow/frontend/src/locales/zh-CN.json +++ b/apps/jingrow/frontend/src/locales/zh-CN.json @@ -17,7 +17,7 @@ "Pending Review": "待审核", "Dashboard": "仪表板", "Agents": "AI智能体", - "Settings": "设置", + "Settings": "系统设置", "Agent Detail": "智能体详情", "Flow Builder": "流程编排", "Profile": "个人资料", diff --git a/apps/jingrow/frontend/src/views/HomePage.vue b/apps/jingrow/frontend/src/views/HomePage.vue new file mode 100644 index 0000000..a7a4a01 --- /dev/null +++ b/apps/jingrow/frontend/src/views/HomePage.vue @@ -0,0 +1,1602 @@ + + + + + diff --git a/apps/jingrow/jingrow/services/whitelist.py b/apps/jingrow/jingrow/services/whitelist.py index 6b0990e..cbf6da0 100644 --- a/apps/jingrow/jingrow/services/whitelist.py +++ b/apps/jingrow/jingrow/services/whitelist.py @@ -60,15 +60,6 @@ async def authenticate_request(request: Request, allow_guest: bool) -> bool: async def _process_whitelist_call(request: Request, full_module_path: str): """通用处理:接收完整点分路径 '' 并执行调用""" try: - async def _get_request_data(req: Request) -> Dict[str, Any]: - """GET 使用查询参数,其他方法使用 JSON body""" - if req.method == 'GET': - return dict(req.query_params) - try: - return await req.json() - except Exception: - return {} - # 确保 apps 目录在 sys.path 中(支持跨 app 导入) ensure_apps_on_sys_path() @@ -96,8 +87,28 @@ async def _process_whitelist_call(request: Request, full_module_path: str): if not await authenticate_request(request, whitelist_info['allow_guest']): raise HTTPException(status_code=401, detail="Authentication required") + # 根据请求类型获取数据 + if request.method == 'GET': + request_data = dict(request.query_params) + else: + # 检查 Content-Type 是否为 multipart/form-data + content_type = request.headers.get('content-type', '') + is_multipart = 'multipart/form-data' in content_type + + if is_multipart: + # 处理文件上传 + form = await request.form() + request_data = {} + for key, value in form.items(): + request_data[key] = value + else: + # 处理 JSON body + try: + request_data = await request.json() + except Exception: + request_data = {} + # 调用函数(只有通过白名单验证的函数才能执行到这里) - request_data = await _get_request_data(request) result = func(**request_data) return JSONResponse(content={"success": True, "data": result}) diff --git a/apps/jingrow/jingrow/tools/remove_background/remove_background.py b/apps/jingrow/jingrow/tools/remove_background/remove_background.py index ed4921f..c4ba473 100644 --- a/apps/jingrow/jingrow/tools/remove_background/remove_background.py +++ b/apps/jingrow/jingrow/tools/remove_background/remove_background.py @@ -15,6 +15,127 @@ from jingrow.utils.auth import get_jingrow_cloud_api_headers, get_jingrow_cloud_ logger = logging.getLogger(__name__) +@jingrow.whitelist(allow_guest=True) +def remove_background_from_file_free(file) -> Dict[str, Any]: + """ + 免费图片去背景工具(无需认证) + 参考 remove_background_from_file 实现,调用 Jingrow Cloud API 实现图片背景移除 + + Args: + file: 上传的文件对象 + + Returns: + dict: 处理结果,格式与 remove_background_from_file 一致 + """ + try: + # 获取认证头(使用系统配置的 API Key) + headers = get_jingrow_cloud_api_headers() + + if not headers or not headers.get('Authorization'): + return { + "success": False, + "error": "API密钥未设置,请联系管理员配置" + } + + # 读取文件内容 + # whitelist 服务传递的 file 是 FastAPI 的 UploadFile 对象 + # UploadFile.file 是底层的 SpooledTemporaryFile,可以同步读取 + # 需要先重置文件指针到开头(因为可能已经被读取过) + file.file.seek(0) + file_content = file.file.read() + + if not file_content or len(file_content) == 0: + return { + "success": False, + "error": "文件内容为空" + } + + # 获取文件扩展名和内容类型 + filename = getattr(file, 'filename', None) or 'image.png' + ext = filename.split('.')[-1].lower() if '.' in filename else 'png' + if ext == 'jpg': + ext = 'jpg' + content_type = 'image/jpeg' + elif ext == 'jpeg': + ext = 'jpg' + content_type = 'image/jpeg' + elif ext == 'png': + ext = 'png' + content_type = 'image/png' + elif ext == 'webp': + ext = 'webp' + content_type = 'image/webp' + else: + ext = 'png' + content_type = 'image/png' + + # 处理EXIF orientation(参考 remove_background_from_file) + image = Image.open(io.BytesIO(file_content)) + image = ImageOps.exif_transpose(image) + output = io.BytesIO() + save_format = image.format or content_type.split('/')[-1].upper() + image.save(output, format=save_format) + image_bytes = output.getvalue() + + # 调用文件上传端点(与 remove_background_from_file 使用相同的接口) + api_url = f"{get_jingrow_cloud_api_url()}/rmbg/file/free" + + # 移除 Content-Type,让 requests 自动设置 multipart/form-data + upload_headers = {k: v for k, v in headers.items() if k.lower() != 'content-type'} + files = { + 'file': (f'image.{ext}', image_bytes, content_type) + } + + # 转发请求 + response = requests.post( + api_url, + files=files, + headers=upload_headers, + timeout=180 + ) + + if response.status_code == 200: + result_data = response.json() + + # 使用 image_url 字段,返回格式与 remove_background_from_file 一致 + if 'image_url' in result_data: + image_url = result_data.get('image_url', '') + return { + "success": True, + "data": [{ + "success": True, + "image_url": image_url, + "index": 1, + "total": 1 + }], + "total_processed": 1, + "total_success": 1 + } + + return { + "success": False, + "error": result_data.get('error', '未找到图片URL') + } + else: + try: + error_data = response.json() + error_message = error_data.get("message") or error_data.get("error") or f"API请求失败 (HTTP {response.status_code})" + except: + error_message = f"API请求失败 (HTTP {response.status_code})" + + return { + "success": False, + "error": error_message + } + + except Exception as e: + logger.error(f"调用图片去背景API异常:{str(e)}", exc_info=True) + return { + "success": False, + "error": f"调用图片去背景API异常:{str(e)}" + } + + @jingrow.whitelist() def remove_background_from_file(image_data: Union[str, list]) -> Dict[str, Any]: """