| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- $(function()
- {
- let timer = null; // 轮询计时器
- let versionIndex = 0; // 当前正在处理的版本索引
- let shouldAbortAll = false; // 标记是否应该中止所有轮询和升级操作
- let currentPollVersion = null; // 标记当前应该处理轮询响应的版本
- function abortUpgrade()
- {
- shouldAbortAll = true;
- stopTimer();
- }
- /**
- * 停止计时器
- */
- function stopTimer()
- {
- if(timer)
- {
- clearTimeout(timer);
- timer = null;
- }
- }
- /**
- * 轮询进度:一直运行直到达到 100%
- */
- function fetchProgress(currentVersion)
- {
- return new Promise((resolve) =>
- {
- currentPollVersion = currentVersion;
- const poll = () =>
- {
- if(shouldAbortAll) return;
- if(currentPollVersion !== currentVersion) return;
- $.getJSON($.createLink('upgrade', 'ajaxGetExecutedChanges'))
- .done(function(response)
- {
- if(shouldAbortAll) return;
- if(currentPollVersion !== currentVersion) return;
- const executedKeys = response.executedKeys;
- $('#changesBox .change-item').not('.executed').each(function()
- {
- const $item = $(this);
- const key = $item.data('key');
- if(executedKeys.includes(key))
- {
- $item.addClass('executed');
- const $label = $item.find('.label');
- $label.text($label.data('text'));
- $label.removeClass('gray-pale text-gray-400').addClass('primary-pale text-primary');
- }
- });
- const $executedItems = $('#changesBox .change-item.executed');
- const $lastExecuted = $executedItems.last();
- if($lastExecuted.length)
- {
- const $nextItem = $lastExecuted.next('.change-item');
- const scrollItem = $nextItem.length ? $nextItem[0] : $lastExecuted[0];
- scrollItem.scrollIntoView({behavior: 'smooth', block: 'nearest'});
- }
- $('#executedCount').text($executedItems.length);
- const keyLength = executedKeys.length;
- if(keyLength && executedKeys[keyLength - 1] != keyLength - 1)
- {
- console.log(response);
- console.warn('Detected missing executed change keys. Aborting upgrade to prevent inconsistencies.');
- abortUpgrade();
- return;
- }
- if(response.allChangesExecuted)
- {
- stopTimer();
- /* 延迟 0.5 秒便于用户看清最后的进度变化。*/
- setTimeout(() =>
- {
- if(currentPollVersion === currentVersion) resolve();
- }, 500);
- return;
- }
- stopTimer();
- if(currentPollVersion === currentVersion) timer = setTimeout(poll, 500);
- })
- .fail(function()
- {
- console.warn('Failed to fetch upgrade progress. Retrying...');
- stopTimer();
- if(currentPollVersion === currentVersion) timer = setTimeout(poll, 500);
- });
- };
- poll(); // 立即开始轮询
- });
- }
- /**
- * 执行升级操作
- */
- async function runUpgrade()
- {
- const totalVersions = upgradeVersions.length;
- while(versionIndex < totalVersions)
- {
- currentPollVersion = null; // 清理上个版本的标记
- const currentVersion = upgradeVersions[versionIndex];
- const isLastVersion = versionIndex === totalVersions - 1;
- let upgradeResult = null;
- /* 发起请求执行升级操作 */
- const upgradePromise = new Promise((resolve, reject) =>
- {
- $.getJSON($.createLink('upgrade', 'ajaxExecute', 'fromVersion=' + fromVersion + '&toVersion=' + currentVersion))
- .done(resolve)
- .fail(reject);
- });
- /* 更新版本列表状态为正在升级 */
- const $versionItem = $('#versionsBox .version-item[data-version="' + currentVersion + '"]');
- $versionItem[0].scrollIntoView({behavior: 'smooth', block: 'nearest'});
- $versionItem.find('.icon-clock').replaceWith('<i class="icon icon-spinner-indicator text-gray-400 w-4 h-4"></i>');
- /* 启动轮询获取升级进度 */
- const pollPromise = fetchProgress(currentVersion);
- /* 等待升级请求完成 */
- try
- {
- upgradeResult = await upgradePromise;
- }
- catch(error)
- {
- /* 升级操作执行失败(网络或 HTTP 错误)*/
- abortUpgrade();
- console.error('Upgrade failed:', error);
- console.warn('An error occurred during the upgrade process. Please try again.');
- return;
- }
- /* 升级请求失败跳转到错误页面 */
- if(upgradeResult.result === 'fail')
- {
- abortUpgrade();
- const url = $.createLink('upgrade', 'execute', 'fromVersion=' + fromVersion);
- const data = new FormData();
- data.append('errors', upgradeResult.message);
- postAndLoadPage(url, data);
- return;
- }
- /* 即使升级请求完成也要等待轮询进度达到 100% */
- await pollPromise;
- /* 更新版本列表状态为升级完成 */
- $versionItem.find('.icon-spinner-indicator').replaceWith('<span class="bg-success rounded-full w-4 h-4"></span>');
- /* 更新版本升级进度条 */
- const executedVersions = versionIndex + 1;
- const progressPercent = Math.round(((executedVersions) / totalVersions) * 100);
- $('#versionsProgressText').text(executedVersions);
- $('#versionsProgressBar .progress-bar').css('width', progressPercent + '%');
- /* 如果是最后一个版本并且返回了跳转链接则跳转到新页面 */
- if(isLastVersion && upgradeResult.load)
- {
- abortUpgrade();
- $('#continueBtn').removeClass('disabled').attr('href', upgradeResult.load);
- return;
- }
- /* 局部刷新加载下一个版本的变更列表 */
- versionIndex++;
- if(versionIndex < totalVersions)
- {
- await new Promise((resolve) =>
- {
- loadCurrentPage(
- {
- selector: '#changesBlock',
- complete: () =>
- {
- const firstChange = $('#changesBox .change-item').first();
- if(firstChange.length)
- {
- firstChange[0].scrollIntoView({behavior: 'smooth', block: 'nearest'});
- }
- resolve();
- }
- });
- });
- }
- }
- stopTimer();
- }
- if(upgradeVersions.length > 0)
- {
- runUpgrade();
- }
- });
- window.showSQL = function(sql)
- {
- zui.Modal.alert({size: 'lg', title: 'SQL', content: {html: sql, className: 'leading-6'}});
- }
|