实现应用市场从文件URL安装应用的功能
This commit is contained in:
parent
42834c913a
commit
4504c3e8bf
@ -140,6 +140,7 @@ import { NInput, NButton, NIcon, NSpin, NEmpty, NSelect, NPagination, useMessage
|
||||
import { Icon } from '@iconify/vue'
|
||||
import axios from 'axios'
|
||||
import { t } from '@/shared/i18n'
|
||||
import { get_session_api_headers } from '@/shared/api/auth'
|
||||
|
||||
const message = useMessage()
|
||||
const router = useRouter()
|
||||
@ -212,9 +213,33 @@ function viewAppDetail(app: any) {
|
||||
router.push(`/app-marketplace/${app.name}`)
|
||||
}
|
||||
|
||||
function installApp(_app: any) {
|
||||
// TODO: 实现安装应用
|
||||
message.info(t('Install feature coming soon'))
|
||||
async function installApp(app: any) {
|
||||
try {
|
||||
if (!app.file_url) {
|
||||
message.error(t('应用文件URL不存在'))
|
||||
return
|
||||
}
|
||||
|
||||
const response = await axios.post('/jingrow/install-from-url', new URLSearchParams({
|
||||
url: app.file_url
|
||||
}), {
|
||||
headers: {
|
||||
...get_session_api_headers(),
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
})
|
||||
|
||||
if (response.data.success) {
|
||||
message.success(t('应用安装成功'))
|
||||
// 刷新列表或跳转到已安装应用页面
|
||||
router.push('/installed-apps')
|
||||
} else {
|
||||
message.error(response.data.error || t('安装失败'))
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Install app error:', error)
|
||||
message.error(error.response?.data?.detail || t('安装失败'))
|
||||
}
|
||||
}
|
||||
|
||||
function getImageUrl(imageUrl: string): string {
|
||||
|
||||
@ -441,6 +441,115 @@ async def get_installed_apps(request: Request):
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.post("/jingrow/install-from-url")
|
||||
async def install_from_url(url: str = Form(...)):
|
||||
"""从URL安装应用或扩展包"""
|
||||
try:
|
||||
# 下载文件
|
||||
import tempfile
|
||||
import requests
|
||||
|
||||
current = Path(__file__).resolve()
|
||||
root = current.parents[4]
|
||||
tmp_dir = root / "tmp"
|
||||
tmp_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 创建临时文件
|
||||
temp_filename = f"download_{uuid.uuid4().hex[:8]}{Path(url).suffix}"
|
||||
temp_file_path = tmp_dir / temp_filename
|
||||
|
||||
# 下载文件
|
||||
response = requests.get(url, stream=True, timeout=300)
|
||||
response.raise_for_status()
|
||||
|
||||
with open(temp_file_path, 'wb') as f:
|
||||
for chunk in response.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
|
||||
# 使用现有的 install_app 函数安装
|
||||
try:
|
||||
result = install_app(str(temp_file_path), None)
|
||||
|
||||
if result.get('success'):
|
||||
app_name_result = result.get('app_name')
|
||||
backend_result = result.get('backend_result', {})
|
||||
app_dir = backend_result.get('app_dir')
|
||||
|
||||
# 扩展包不添加到 Local Installed Apps(返回时没有 app_dir)
|
||||
if not app_dir:
|
||||
return result
|
||||
|
||||
# 对齐扫描安装的执行链
|
||||
try:
|
||||
# 1. 添加到 Local Installed Apps PageType
|
||||
from jingrow.utils.jingrow_api import get_single_pagetype
|
||||
pagetype_result = get_single_pagetype("Local Installed Apps")
|
||||
if pagetype_result.get('success'):
|
||||
config = pagetype_result.get('config', {})
|
||||
apps_list = config.get('local_installed_apps', [])
|
||||
else:
|
||||
apps_list = []
|
||||
|
||||
# 检查是否已存在,如果存在则更新,否则添加
|
||||
app_exists = False
|
||||
for app in apps_list:
|
||||
if app.get('app_name', '') == app_name_result:
|
||||
app['app_version'] = '1.0.0'
|
||||
app['git_branch'] = 'main'
|
||||
app_exists = True
|
||||
break
|
||||
|
||||
if not app_exists:
|
||||
apps_list.append({
|
||||
'app_name': app_name_result,
|
||||
'app_version': '1.0.0',
|
||||
'git_branch': 'main'
|
||||
})
|
||||
|
||||
# 更新数据库
|
||||
await _update_local_installed_apps(apps_list)
|
||||
|
||||
# 2. 调用 sync_app_files 同步文件到数据库
|
||||
if app_dir:
|
||||
current = Path(__file__).resolve()
|
||||
root = current.parents[4]
|
||||
apps_dir = root / "apps"
|
||||
backend_dir = apps_dir / app_name_result / app_name_result
|
||||
if not backend_dir.exists():
|
||||
backend_dir = apps_dir / app_name_result
|
||||
|
||||
if backend_dir.exists():
|
||||
try:
|
||||
api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.sync_app_files"
|
||||
requests.post(
|
||||
api_url,
|
||||
json={'app_name': app_name_result, 'app_path': str(backend_dir), 'force': True},
|
||||
headers=get_jingrow_api_headers(),
|
||||
timeout=60
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return result
|
||||
else:
|
||||
raise HTTPException(status_code=400, detail=result.get('error', '安装失败'))
|
||||
finally:
|
||||
# 清理下载的文件
|
||||
try:
|
||||
if temp_file_path.exists():
|
||||
os.unlink(temp_file_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.post("/jingrow/uninstall-extension/{package_name}")
|
||||
async def uninstall_extension(request: Request, package_name: str):
|
||||
"""卸载扩展包 - 先获取模块列表,卸载数据库,再删除本地目录"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user