将应用商店的用户实例保存到数据库
This commit is contained in:
@@ -128,6 +128,25 @@
|
||||
font-size: 1em !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 修复应用详情页面中网站和仓库按钮的文字对齐问题 */
|
||||
#app-details-modal .ui.buttons .ui.button {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
height: 2.5em !important;
|
||||
line-height: 1 !important;
|
||||
}
|
||||
|
||||
#app-details-modal .ui.buttons .ui.button i.icon {
|
||||
margin-right: 0.5em !important;
|
||||
line-height: 1 !important;
|
||||
}
|
||||
|
||||
#app-details-modal .ui.buttons .ui.button:not(.icon) {
|
||||
padding-left: 1em !important;
|
||||
padding-right: 1em !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="ui stackable grid">
|
||||
@@ -331,7 +350,7 @@
|
||||
<div class="actions">
|
||||
<div class="ui button" onclick="closeDetailsModal()">{{ctx.Locale.Tr "cancel"}}</div>
|
||||
<div class="ui primary button" onclick="updateInstalledAppFromDetails()">更新应用</div>
|
||||
<div class="ui orange button" onclick="stopCurrentAppFromDetails()">暂停应用</div>
|
||||
<div class="ui orange button" id="pause-resume-btn" onclick="togglePauseResumeFromDetails()">暂停应用</div>
|
||||
<div class="ui red button" onclick="uninstallCurrentAppFromDetails()">卸载应用</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1046,8 +1065,8 @@ async function checkAppInstallStatus(app) {
|
||||
const replicas = data.replicas ?? data.status?.replicas ?? 0;
|
||||
const readyReplicas = data.readyReplicas ?? data.status?.readyReplicas ?? 0;
|
||||
|
||||
// 判断是否已安装且就绪
|
||||
const isInstalled = phase !== 'Not Installed' && phase !== 'Unknown' && (replicas === 0 || readyReplicas > 0);
|
||||
// 判断是否已安装(包括暂停状态)
|
||||
const isInstalled = phase !== 'Not Installed' && phase !== 'Unknown';
|
||||
|
||||
if (isInstalled) {
|
||||
installBtn.className = 'ui green compact button disabled';
|
||||
@@ -1087,41 +1106,54 @@ function uninstallCurrentAppFromDetails() {
|
||||
uninstallForm.submit();
|
||||
}
|
||||
|
||||
// 暂停应用(从详情弹窗触发)
|
||||
function stopCurrentAppFromDetails() {
|
||||
// 暂停/恢复应用(从详情弹窗触发)
|
||||
function togglePauseResumeFromDetails() {
|
||||
if (!currentApp) return;
|
||||
const appId = currentApp.id || currentApp.app_id;
|
||||
|
||||
// 根据当前状态决定操作
|
||||
const isRunning = currentAppStatus && currentAppStatus.replicas > 0;
|
||||
const action = isRunning ? 'stop' : 'resume';
|
||||
const actionText = isRunning ? '暂停' : '恢复';
|
||||
const confirmText = isRunning ?
|
||||
'确定要暂停应用吗?暂停后应用将停止运行,但数据会保留。' :
|
||||
'确定要恢复应用吗?应用将重新开始运行。';
|
||||
|
||||
// 显示确认对话框
|
||||
if (!confirm('确定要暂停应用吗?暂停后应用将停止运行,但数据会保留。')) {
|
||||
if (!confirm(confirmText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建暂停应用的请求
|
||||
const stopForm = document.createElement('form');
|
||||
stopForm.method = 'POST';
|
||||
stopForm.action = `/user/settings/appstore/stop/${appId}`;
|
||||
// 创建暂停/恢复应用的请求
|
||||
const form = document.createElement('form');
|
||||
form.method = 'POST';
|
||||
form.action = `/user/settings/appstore/${action}/${appId}`;
|
||||
|
||||
const csrfInput = document.createElement('input');
|
||||
csrfInput.type = 'hidden';
|
||||
csrfInput.name = '_csrf';
|
||||
csrfInput.value = document.querySelector('meta[name="_csrf"]')?.content || '';
|
||||
stopForm.appendChild(csrfInput);
|
||||
form.appendChild(csrfInput);
|
||||
|
||||
const appIdInput = document.createElement('input');
|
||||
appIdInput.type = 'hidden';
|
||||
appIdInput.name = 'app_id';
|
||||
appIdInput.value = appId;
|
||||
stopForm.appendChild(appIdInput);
|
||||
form.appendChild(appIdInput);
|
||||
|
||||
const redirectInput = document.createElement('input');
|
||||
redirectInput.type = 'hidden';
|
||||
redirectInput.name = 'redirect_to';
|
||||
redirectInput.value = window.location.pathname;
|
||||
stopForm.appendChild(redirectInput);
|
||||
form.appendChild(redirectInput);
|
||||
|
||||
document.body.appendChild(stopForm);
|
||||
stopForm.submit();
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
|
||||
// 暂停应用(从详情弹窗触发)- 保留向后兼容
|
||||
function stopCurrentAppFromDetails() {
|
||||
togglePauseResumeFromDetails();
|
||||
}
|
||||
|
||||
// 加载并渲染运行状态(基于 K8s Application CRD)
|
||||
@@ -1169,13 +1201,13 @@ async function loadAndRenderAppStatus(app) {
|
||||
// 根据应用状态动态控制操作按钮的显示
|
||||
function updateActionButtonsVisibility() {
|
||||
const updateBtn = document.querySelector('#app-details-modal .ui.primary.button[onclick="updateInstalledAppFromDetails()"]');
|
||||
const stopBtn = document.querySelector('#app-details-modal .ui.orange.button[onclick="stopCurrentAppFromDetails()"]');
|
||||
const pauseResumeBtn = document.getElementById('pause-resume-btn');
|
||||
const uninstallBtn = document.querySelector('#app-details-modal .ui.red.button[onclick="uninstallCurrentAppFromDetails()"]');
|
||||
|
||||
if (!currentAppStatus) {
|
||||
// 状态未知,隐藏所有操作按钮
|
||||
if (updateBtn) updateBtn.style.display = 'none';
|
||||
if (stopBtn) stopBtn.style.display = 'none';
|
||||
if (pauseResumeBtn) pauseResumeBtn.style.display = 'none';
|
||||
if (uninstallBtn) uninstallBtn.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
@@ -1189,9 +1221,21 @@ function updateActionButtonsVisibility() {
|
||||
updateBtn.style.display = isInstalled ? 'inline-block' : 'none';
|
||||
}
|
||||
|
||||
// 暂停按钮:只有正在运行的应用才能暂停
|
||||
if (stopBtn) {
|
||||
stopBtn.style.display = isRunning ? 'inline-block' : 'none';
|
||||
// 暂停/恢复按钮:已安装的应用可以暂停或恢复
|
||||
if (pauseResumeBtn) {
|
||||
if (isInstalled) {
|
||||
pauseResumeBtn.style.display = 'inline-block';
|
||||
// 根据应用状态更新按钮文本和样式
|
||||
if (isRunning) {
|
||||
pauseResumeBtn.textContent = '暂停应用';
|
||||
pauseResumeBtn.className = 'ui orange button';
|
||||
} else if (isStopped) {
|
||||
pauseResumeBtn.textContent = '恢复应用';
|
||||
pauseResumeBtn.className = 'ui green button';
|
||||
}
|
||||
} else {
|
||||
pauseResumeBtn.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// 卸载按钮:只有已安装的应用才能卸载
|
||||
@@ -1295,49 +1339,9 @@ async function installApp() {
|
||||
installBtn.disabled = true;
|
||||
}
|
||||
|
||||
// 异步提交,成功后更新按钮状态
|
||||
try {
|
||||
const formData = new FormData(installForm);
|
||||
const response = await fetch(installForm.action, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// 安装成功,更新按钮状态
|
||||
const appId = currentApp.id || currentApp.app_id;
|
||||
const cardInstallBtn = document.getElementById(`install-btn-${appId}`);
|
||||
if (cardInstallBtn) {
|
||||
cardInstallBtn.className = 'ui green compact button disabled';
|
||||
cardInstallBtn.innerHTML = '<i class="check icon"></i>已安装';
|
||||
cardInstallBtn.onclick = null;
|
||||
}
|
||||
|
||||
closeInstallModal();
|
||||
// 显示成功消息
|
||||
alert('应用安装成功!');
|
||||
} else {
|
||||
// 安装失败,恢复按钮状态
|
||||
if (installBtn) {
|
||||
installBtn.className = 'ui primary button';
|
||||
installBtn.textContent = '安装应用';
|
||||
installBtn.disabled = false;
|
||||
}
|
||||
const errorData = await response.json();
|
||||
alert('安装失败: ' + (errorData.error || '未知错误'));
|
||||
}
|
||||
} catch (error) {
|
||||
// 网络错误,恢复按钮状态
|
||||
if (installBtn) {
|
||||
installBtn.className = 'ui primary button';
|
||||
installBtn.textContent = '安装应用';
|
||||
installBtn.disabled = false;
|
||||
}
|
||||
alert('安装失败: ' + error.message);
|
||||
}
|
||||
|
||||
// 清理表单
|
||||
document.body.removeChild(installForm);
|
||||
// 与卸载一致:使用表单直接提交,后端重定向以显示绿色提示
|
||||
installForm.submit();
|
||||
return;
|
||||
}
|
||||
|
||||
function showAddAppModal() {
|
||||
|
||||
Reference in New Issue
Block a user