feat: add homepage background removal tool and fix whitelist multipart support
- Add HomePage.vue with background removal functionality - Fix whitelist service to support multipart/form-data file uploads - Remove unused imports
This commit is contained in:
parent
1d20385e96
commit
6292b8b510
@ -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 },
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
"Pending Review": "待审核",
|
||||
"Dashboard": "仪表板",
|
||||
"Agents": "AI智能体",
|
||||
"Settings": "设置",
|
||||
"Settings": "系统设置",
|
||||
"Agent Detail": "智能体详情",
|
||||
"Flow Builder": "流程编排",
|
||||
"Profile": "个人资料",
|
||||
|
||||
1602
apps/jingrow/frontend/src/views/HomePage.vue
Normal file
1602
apps/jingrow/frontend/src/views/HomePage.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -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):
|
||||
"""通用处理:接收完整点分路径 '<package.module.function>' 并执行调用"""
|
||||
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})
|
||||
|
||||
@ -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]:
|
||||
"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user