diff --git a/apps/jingrow/frontend/src/views/dev/AppMarketplace.vue b/apps/jingrow/frontend/src/views/dev/AppMarketplace.vue
index a01cf6d..1710049 100644
--- a/apps/jingrow/frontend/src/views/dev/AppMarketplace.vue
+++ b/apps/jingrow/frontend/src/views/dev/AppMarketplace.vue
@@ -94,7 +94,18 @@
{{ t('View Details') }}
-
+
+ {{ t('Update') }}
+
+
{{ t('Install') }}
@@ -171,6 +182,9 @@ const installMessage = ref('')
const installStatus = ref<'success' | 'error' | 'info'>('info')
const showProgressModal = ref(false)
+// 已安装应用集合
+const installedAppNames = ref>(new Set())
+
// 排序选项
const sortOptions = computed(() => [
{ label: t('Latest'), value: 'creation desc' },
@@ -300,6 +314,9 @@ async function performInstall(app: any) {
installMessage.value = t('应用安装成功!')
message.success(t('应用安装成功'))
+ // 刷新已安装应用列表
+ loadInstalledApps()
+
setTimeout(() => {
showProgressModal.value = false
}, 2000)
@@ -341,8 +358,41 @@ function truncateText(text: string, maxLength: number): string {
return text.substring(0, maxLength) + '...'
}
+// 加载已安装应用列表
+async function loadInstalledApps() {
+ try {
+ const cached = sessionStorage.getItem('installed_apps_names')
+ if (cached) {
+ const data = JSON.parse(cached)
+ if (Date.now() - data.timestamp < 30 * 60 * 1000) {
+ installedAppNames.value = new Set(data.apps || [])
+ return
+ }
+ }
+
+ const response = await axios.get('/jingrow/installed-app-names')
+ if (response.data.success) {
+ const apps = response.data.apps || []
+ installedAppNames.value = new Set(apps)
+ sessionStorage.setItem('installed_apps_names', JSON.stringify({
+ apps,
+ timestamp: Date.now()
+ }))
+ }
+ } catch (error) {
+ console.error('Load installed apps error:', error)
+ }
+}
+
+// 检查应用是否已安装
+function isAppInstalled(appName: string): boolean {
+ if (!appName) return false
+ return installedAppNames.value.has(appName.toLowerCase())
+}
+
onMounted(() => {
loadApps()
+ loadInstalledApps()
})
// 监听搜索和排序变化
diff --git a/apps/jingrow/jingrow/api/local_app_installer.py b/apps/jingrow/jingrow/api/local_app_installer.py
index f5d11a2..53dae00 100644
--- a/apps/jingrow/jingrow/api/local_app_installer.py
+++ b/apps/jingrow/jingrow/api/local_app_installer.py
@@ -220,6 +220,37 @@ async def check_app_exists(app_name: str):
return {'exists': False, 'installed': False, 'error': str(e)}
+@router.get("/jingrow/installed-app-names")
+async def get_installed_app_names():
+ """获取所有已安装的应用名称列表"""
+ try:
+ from jingrow.utils.jingrow_api import get_single_pagetype, get_record_list
+
+ installed = set()
+
+ # 从 Local Installed Apps 获取应用列表
+ result = get_single_pagetype("Local Installed Apps")
+ if result.get('success'):
+ config = result.get('config', {})
+ local_installed_apps = config.get('local_installed_apps', [])
+ for app in local_installed_apps:
+ app_name = app.get('app_name', '')
+ if app_name:
+ installed.add(app_name.lower())
+
+ # 从 Package PageType 获取扩展包列表
+ package_result = get_record_list("Package", fields=["name"], limit=1000)
+ if package_result.get('success') and package_result.get('data'):
+ for pkg in package_result.get('data', []):
+ pkg_name = pkg.get('name', '')
+ if pkg_name:
+ installed.add(pkg_name.lower())
+
+ return {'success': True, 'apps': list(installed)}
+ except Exception as e:
+ return {'success': False, 'error': str(e), 'apps': []}
+
+
@router.get("/jingrow/local-apps")
async def get_local_apps(request: Request):
"""扫描本地未安装的App"""