feat: Support managing application upgrades for all nodes on a single page (#11325)

This commit is contained in:
CityFun 2025-12-12 18:49:10 +08:00 committed by GitHub
parent 6f9a8d5afe
commit 956a64c692
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 59 additions and 9 deletions

View file

@ -169,6 +169,7 @@ var WebUrlMap = map[string]struct{}{
"/xpack/simple-node": {},
"/xpack/exchange/file": {},
"/xpack/app": {},
"/xpack/app-upgrade": {},
"/xpack/cluster/mysql": {},
"/xpack/cluster/postgres": {},

View file

@ -287,4 +287,9 @@ export namespace Setting {
smsUsed: number;
smsTotal: number;
}
export interface NodeAppItem {
name: string;
updateCount: number;
}
}

View file

@ -41,8 +41,9 @@ export const changePort = (params: App.ChangePort) => {
return http.post<any>('apps/installed/port/change', params);
};
export const searchAppInstalled = (search: App.AppInstallSearch) => {
return http.post<ResPage<App.AppInstallDto>>('apps/installed/search', search);
export const searchAppInstalled = (search: App.AppInstallSearch, node?: string) => {
const params = node ? `?operateNode=${node}` : '';
return http.post<ResPage<App.AppInstallDto>>(`apps/installed/search${params}`, search);
};
export const listAppInstalled = () => {
@ -89,8 +90,9 @@ export const getAppService = (key: string | undefined, node?: string) => {
return http.get<App.AppService[]>(`apps/services/${key}${params}`);
};
export const getAppUpdateVersions = (req: App.AppUpdateVersionReq) => {
return http.post<any>(`apps/installed/update/versions`, req);
export const getAppUpdateVersions = (req: App.AppUpdateVersionReq, node?: string) => {
const params = node ? `?operateNode=${node}` : '';
return http.post<any>(`apps/installed/update/versions${params}`, req);
};
export const getAppDefaultConfig = (key: string, name: string) => {

View file

@ -55,6 +55,10 @@ export const getLicenseSmsInfo = () => {
return http.get<Setting.SmsInfo>(`/core/licenses/sms/info`);
};
export const listAppNodes = () => {
return http.get<Array<Setting.NodeAppItem>>(`/core/xpack/nodes/apps/update`);
};
// agent
export const loadBaseDir = () => {
return http.get<string>(`/settings/basedir`);

View file

@ -3817,6 +3817,9 @@ const message = {
offline: 'Offline mode',
freeCount: 'Free quota [{0}]',
offlineHelper: 'Used when the node is in an offline environment',
appUpgrade: 'App Upgrade',
appUpgradeHelper: 'There are {0} apps that need to be upgraded',
},
customApp: {
name: 'Custom App Repository',

View file

@ -3771,6 +3771,9 @@ const message = {
offline: 'Modo Offline',
freeCount: 'Cuota gratuita [{0}]',
offlineHelper: 'Usado cuando el nodo está en un entorno sin conexión',
appUpgrade: 'Actualización de la aplicación',
appUpgradeHelper: 'Hay {0} aplicaciones que necesitan ser actualizadas',
},
customApp: {
name: 'Repositorio de Apps Personalizadas',

View file

@ -3705,6 +3705,9 @@ const message = {
offline: 'オフラインモード',
freeCount: '無料枠 [{0}]',
offlineHelper: 'ノードがオフライン環境にある場合に使用',
appUpgrade: 'アプリのアップグレード',
appUpgradeHelper: 'アップグレードが必要なアプリが {0} 個あります',
},
customApp: {
name: 'カスタムアプリリポジトリ',

View file

@ -3636,6 +3636,9 @@ const message = {
offline: '오프라인 모드',
freeCount: '무료 할당량 [{0}]',
offlineHelper: '노드가 오프라인 환경일 사용',
appUpgrade: ' 업그레이드',
appUpgradeHelper: '업그레이드가 필요한 앱이 {0} 있습니다',
},
customApp: {
name: '사용자 정의 저장소',

View file

@ -3774,6 +3774,9 @@ const message = {
offline: 'Mod luar talian',
freeCount: 'Had percuma [{0}]',
offlineHelper: 'Digunakan apabila nod berada dalam persekitaran luar talian',
appUpgrade: 'Naik Taraf Apl',
appUpgradeHelper: 'Terdapat {0} apl yang perlu dinaik taraf',
},
customApp: {
name: 'Repositori Aplikasi Khusus',

View file

@ -3793,6 +3793,9 @@ const message = {
offline: 'Modo offline',
freeCount: 'Cota gratuita [{0}]',
offlineHelper: 'Usado quando o está em ambiente offline',
appUpgrade: 'Atualização do Aplicativo',
appUpgradeHelper: 'Existem {0} aplicativos que precisam ser atualizados',
},
customApp: {
name: 'Repositório de Aplicativos Personalizados',

View file

@ -3781,6 +3781,9 @@ const message = {
offline: 'Автономный режим',
freeCount: 'Бесплатная квота [{0}]',
offlineHelper: 'Используется, когда узел находится в автономной среде',
appUpgrade: 'Обновление приложения',
appUpgradeHelper: 'Есть {0} приложений, которые необходимо обновить',
},
customApp: {
name: 'Пользовательское хранилище приложений',

View file

@ -3856,6 +3856,9 @@ const message = {
offline: 'Çevrimdışı mod',
freeCount: 'Ücretsiz kota [{0}]',
offlineHelper: 'Düğüm çevrimdışı bir ortamda olduğunda kullanılır',
appUpgrade: 'Uygulama Yükseltme',
appUpgradeHelper: 'Yükseltilmesi gereken {0} uygulama var',
},
customApp: {
name: 'Özel Uygulama Deposu',

View file

@ -3519,6 +3519,9 @@ const message = {
offline: '離線模式',
freeCount: '免費額度 [{0}]',
offlineHelper: '當節點處於離線環境時使用',
appUpgrade: '應用程式升級',
appUpgradeHelper: ' {0} 個應用程式需要升級',
},
customApp: {
name: '自訂應用倉庫',

View file

@ -3513,6 +3513,9 @@ const message = {
offline: '离线模式',
freeCount: '免费额度 [{0}] ',
offlineHelper: '节点为离线环境时使用',
appUpgrade: '应用升级',
appUpgradeHelper: ' {0} 个应用需要升级',
},
customApp: {
name: '自定义仓库',

View file

@ -93,6 +93,8 @@ import { MsgSuccess } from '@/utils/message';
import { Rules } from '@/global/form-rules';
import bus from '@/global/bus';
import { v4 as uuidv4 } from 'uuid';
import { useGlobalStore } from '@/composables/useGlobalStore';
const { currentNode } = useGlobalStore();
const composeDiffRef = ref();
const updateRef = ref<FormInstance>();
@ -132,6 +134,7 @@ const ignoreAppReq = reactive({
scope: 'app',
});
const isEdit = ref(false);
const node = ref('');
const toLink = (link: string) => {
window.open(link, '_blank');
@ -155,7 +158,7 @@ const getNewCompose = (compose: string) => {
};
const initData = async () => {
const config = await getAppStoreConfig();
const config = await getAppStoreConfig(node.value);
newCompose.value = '';
useNewCompose.value = false;
operateReq.backup = config.data.upgradeBackup == 'Enable';
@ -163,8 +166,13 @@ const initData = async () => {
operateReq.dockerCompose = '';
};
const acceptParams = (appInstall: App.AppInstallDto, op: string) => {
const acceptParams = (appInstall: App.AppInstallDto, op: string, opNode?: string) => {
initData();
if (opNode) {
node.value = opNode;
} else {
node.value = currentNode.value;
}
isEdit.value = appInstall.isEdit;
operateReq.installId = appInstall.id;
operateReq.operate = op;
@ -188,7 +196,7 @@ const getVersions = async (version: string) => {
req['updateVersion'] = version;
}
try {
const res = await getAppUpdateVersions(req);
const res = await getAppUpdateVersions(req, node.value);
versions.value = res.data || [];
if (res.data != null && res.data.length > 0) {
let item = res.data[0];
@ -205,7 +213,7 @@ const getVersions = async (version: string) => {
};
const openTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID);
taskLogRef.value.openWithTaskID(taskID, true, node.value);
};
const operate = async () => {
@ -216,7 +224,7 @@ const operate = async () => {
}
const taskID = uuidv4();
operateReq.taskID = taskID;
await installedOp(operateReq)
await installedOp(operateReq, node.value)
.then(() => {
bus.emit('upgrade', true);
handleClose();