diff --git a/apps/jingrow/frontend/src/views/dev/MyPublishedApps.vue b/apps/jingrow/frontend/src/views/dev/MyPublishedApps.vue
index 95346fe..fa23345 100644
--- a/apps/jingrow/frontend/src/views/dev/MyPublishedApps.vue
+++ b/apps/jingrow/frontend/src/views/dev/MyPublishedApps.vue
@@ -100,18 +100,10 @@
{{ t('View Details') }}
- {{ t('Update') }}
-
-
- {{ t('Install') }}
+ {{ t('Delete') }}
@@ -151,15 +143,6 @@
-
-
-
@@ -170,8 +153,6 @@ 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'
-import InstallProgressModal from './InstallProgressModal.vue'
const message = useMessage()
const dialog = useDialog()
@@ -185,16 +166,6 @@ const page = ref(1)
const pageSize = ref(parseInt(localStorage.getItem('itemsPerPage') || '20'))
const sortBy = ref('creation desc')
-// 安装相关状态
-const installing = ref(false)
-const installProgress = ref(0)
-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' },
@@ -287,151 +258,56 @@ function getStatusClass(status: string): string {
return status.toLowerCase().replace(/\s+/g, '-')
}
-async function installApp(app: any) {
- if (!app.file_url && !app.repository_url) {
- message.error(t('应用文件URL或仓库地址不存在'))
+async function deleteApp(app: any) {
+ // 使用记录的name字段删除
+ const recordName = app.name
+ if (!recordName) {
+ message.error(t('应用名称不存在'))
return
}
- // 先检查应用是否已存在
- try {
- const appName = app.app_name || app.name
- if (appName) {
- const checkResponse = await axios.get(`/jingrow/check-app/${appName}`)
-
- if (checkResponse.data.exists) {
- // 显示确认对话框
- dialog.warning({
- title: t('应用已存在'),
- content: t('应用 "{0}" 已安装,是否覆盖安装?').replace('{0}', appName),
- positiveText: t('确认覆盖'),
- negativeText: t('取消'),
- onPositiveClick: () => {
- performInstall(app)
- }
- })
- return
- }
+ // 显示确认对话框,显示应用标题
+ const appTitle = app.title || app.app_name || recordName
+ dialog.warning({
+ title: t('确认删除'),
+ content: t('确定要删除应用 "{0}" 吗?此操作不可恢复。').replace('{0}', appTitle),
+ positiveText: t('确认删除'),
+ negativeText: t('取消'),
+ onPositiveClick: async () => {
+ await performDelete(recordName)
}
- } catch (error) {
- console.error('Check app exists error:', error)
- }
-
- performInstall(app)
+ })
}
-async function performInstall(app: any) {
+async function performDelete(appName: string) {
try {
- installing.value = true
- installProgress.value = 0
- installMessage.value = t('正在准备安装...')
- installStatus.value = 'info'
- showProgressModal.value = true
+ // 调用本地API,由后端转发到云端
+ const response = await axios.post('/jingrow/delete-published-app', {
+ name: appName
+ }, {
+ withCredentials: true
+ })
- let response
-
- // 优先使用文件URL,否则使用git仓库
- if (app.file_url) {
- installMessage.value = t('正在下载应用包...')
- setTimeout(() => {
- installProgress.value = 20
- }, 300)
-
- installProgress.value = 30
- installMessage.value = t('正在安装应用...')
-
- 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'
- }
- })
- } else if (app.repository_url) {
- installMessage.value = t('正在克隆仓库...')
- setTimeout(() => {
- installProgress.value = 20
- }, 300)
-
- installProgress.value = 30
- installMessage.value = t('正在安装应用...')
-
- const params = new URLSearchParams({
- repo_url: app.repository_url
- })
-
- response = await axios.post('/jingrow/install-from-git', params, {
- headers: {
- ...get_session_api_headers(),
- 'Content-Type': 'application/x-www-form-urlencoded'
- }
- })
- }
-
- if (!response) {
- throw new Error(t('无法确定安装方式'))
- }
-
- // 更新进度到安装完成
- installProgress.value = 100
-
- if (response.data.success) {
- // 所有步骤完成后才显示成功
- installing.value = false
- installStatus.value = 'success'
- installMessage.value = t('应用安装成功!')
- message.success(t('应用安装成功'))
-
- // 刷新已安装应用列表
- loadInstalledApps()
-
- setTimeout(() => {
- showProgressModal.value = false
- }, 2000)
+ if (response.data && response.data.success) {
+ message.success(response.data.message || t('应用删除成功'))
+ // 刷新应用列表
+ loadApps()
} else {
- throw new Error(response.data.error || t('安装失败'))
+ const errorMsg = response.data?.message || response.data?.error || t('删除失败')
+ message.error(errorMsg)
}
} catch (error: any) {
- console.error('Install app error:', error)
- installing.value = false
- installStatus.value = 'error'
- installMessage.value = error.response?.data?.detail || error.message || t('安装失败')
- message.error(error.response?.data?.detail || t('安装失败'))
-
- setTimeout(() => {
- showProgressModal.value = false
- }, 3000)
+ console.error('Delete app error:', error)
+ const errorMsg = error.response?.data?.detail ||
+ error.response?.data?.message ||
+ error.message ||
+ t('删除失败')
+ message.error(errorMsg)
}
}
-// 加载已安装应用列表
-async function loadInstalledApps() {
- try {
- const response = await axios.get('/jingrow/installed-app-names')
- if (response.data.success) {
- const apps = response.data.apps || []
- installedAppNames.value = new Set(apps)
- }
- } 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()
-
- // 监听全局事件
- window.addEventListener('installedAppsUpdated', () => {
- loadInstalledApps()
- })
})
// 监听搜索和排序变化
diff --git a/apps/jingrow/jingrow/api/local_app_installer.py b/apps/jingrow/jingrow/api/local_app_installer.py
index b37b1a4..2090d51 100644
--- a/apps/jingrow/jingrow/api/local_app_installer.py
+++ b/apps/jingrow/jingrow/api/local_app_installer.py
@@ -1060,6 +1060,36 @@ async def get_my_published_apps(
}
+@router.post("/jingrow/delete-published-app")
+async def delete_published_app(request: Request, payload: Dict[str, Any]):
+ """删除已发布的应用,根据记录的name字段删除"""
+ session_cookie = request.cookies.get('sid')
+ if not session_cookie:
+ raise HTTPException(status_code=401, detail="未提供认证信息")
+
+ # 使用记录的name字段,不是app_name字段
+ record_name = payload.get('name')
+ if not record_name:
+ raise HTTPException(status_code=400, detail="记录名称不能为空")
+
+ url = f"{get_jingrow_cloud_url()}/api/action/jcloud.api.local_app.delete_local_app"
+
+ headers = get_jingrow_cloud_api_headers()
+ headers['Cookie'] = f'sid={session_cookie}'
+
+ # 传递记录的name字段到云端API
+ response = requests.post(url, json={'name': record_name}, headers=headers, timeout=20)
+ response.raise_for_status()
+
+ data = response.json()
+ result = data.get('message', data)
+
+ if result.get('success'):
+ return {"success": True, "message": result.get('message', '应用删除成功')}
+ else:
+ raise HTTPException(status_code=400, detail=result.get('message', '删除失败'))
+
+
@router.post("/jingrow/upload-image")
async def upload_image(file: UploadFile = File(...)):
"""上传应用图片"""