// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
// for details on configuring this project to bundle and minify static web assets.
|
|
// API Base URL (configured server-side)
|
const API_BASE_URL = window.API_BASE_URL || '/api';
|
|
// Show toast notification
|
function showToast(message, type = 'info') {
|
const toastContainer = document.getElementById('toastContainer') || createToastContainer();
|
const toastId = 'toast-' + Date.now();
|
|
const bgClass = {
|
'success': 'bg-success',
|
'danger': 'bg-danger',
|
'warning': 'bg-warning',
|
'info': 'bg-info',
|
'error': 'bg-danger'
|
}[type] || 'bg-info';
|
|
const toastHtml = `
|
<div id="${toastId}" class="toast align-items-center text-white ${bgClass} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
<div class="d-flex">
|
<div class="toast-body">
|
${message}
|
</div>
|
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
</div>
|
</div>
|
`;
|
|
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
|
const toastElement = document.getElementById(toastId);
|
const toast = new bootstrap.Toast(toastElement, { delay: 3000 });
|
toast.show();
|
|
toastElement.addEventListener('hidden.bs.toast', () => {
|
toastElement.remove();
|
});
|
}
|
|
function createToastContainer() {
|
const container = document.createElement('div');
|
container.id = 'toastContainer';
|
container.className = 'toast-container';
|
document.body.appendChild(container);
|
return container;
|
}
|
|
// Show loading spinner
|
function showLoading() {
|
const existingOverlay = document.getElementById('loadingOverlay');
|
if (existingOverlay) return;
|
|
const overlay = document.createElement('div');
|
overlay.id = 'loadingOverlay';
|
overlay.className = 'spinner-overlay';
|
overlay.innerHTML = `
|
<div class="spinner-border text-light" style="width: 3rem; height: 3rem;" role="status">
|
<span class="visually-hidden">Loading...</span>
|
</div>
|
`;
|
document.body.appendChild(overlay);
|
}
|
|
// Hide loading spinner
|
function hideLoading() {
|
const overlay = document.getElementById('loadingOverlay');
|
if (overlay) {
|
overlay.remove();
|
}
|
}
|
|
// API call helper
|
async function apiCall(url, options = {}) {
|
const { silent = false, ...fetchOptions } = options;
|
|
try {
|
if (!silent) {
|
showLoading();
|
}
|
const response = await fetch(url, {
|
...fetchOptions,
|
headers: {
|
'Content-Type': 'application/json',
|
...fetchOptions.headers
|
}
|
});
|
|
if (!response.ok) {
|
const errorData = await response.json().catch(() => ({ error: response.statusText }));
|
throw new Error(errorData.error || `HTTP ${response.status}: ${response.statusText}`);
|
}
|
|
return await response.json();
|
} catch (error) {
|
if (!silent) {
|
showToast(error.message, 'error');
|
}
|
throw error;
|
} finally {
|
if (!silent) {
|
hideLoading();
|
}
|
}
|
}
|
|
// Format date
|
function formatDate(dateString) {
|
if (!dateString) return '-';
|
const date = new Date(dateString);
|
return date.toLocaleString('zh-CN', {
|
year: 'numeric',
|
month: '2-digit',
|
day: '2-digit',
|
hour: '2-digit',
|
minute: '2-digit',
|
second: '2-digit'
|
});
|
}
|
|
// Get status badge class
|
function getStatusBadgeClass(status) {
|
const statusMap = {
|
'Stopped': 'status-stopped',
|
'Starting': 'status-starting',
|
'Running': 'status-running',
|
'Stopping': 'status-stopping',
|
'Error': 'status-error'
|
};
|
return statusMap[status] || 'bg-secondary';
|
}
|
|
// Get status text
|
function getStatusText(status) {
|
const statusMap = {
|
'Stopped': '已停止',
|
'Starting': '启动中',
|
'Running': '运行中',
|
'Stopping': '停止中',
|
'Error': '错误'
|
};
|
return statusMap[status] || status;
|
}
|
|
// Get PLC type text
|
function getPlcTypeText(plcType) {
|
const plcTypeMap = {
|
'S7200Smart': 'S7-200 Smart',
|
'S71200': 'S7-1200',
|
'S71500': 'S7-1500',
|
'S7300': 'S7-300',
|
'S7400': 'S7-400'
|
};
|
return plcTypeMap[plcType] || plcType;
|
}
|
|
// Confirm action
|
function confirmAction(message, callback) {
|
if (confirm(message)) {
|
callback();
|
}
|
}
|
|
// Redirect with delay
|
function redirectWithDelay(url, delay = 1500) {
|
setTimeout(() => {
|
window.location.href = url;
|
}, delay);
|
}
|
|
// Format bytes
|
function formatBytes(bytes, decimals = 2) {
|
if (bytes === 0) return '0 Bytes';
|
const k = 1024;
|
const dm = decimals < 0 ? 0 : decimals;
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
}
|
|
// Auto-refresh interval handler
|
let refreshInterval = null;
|
|
function startAutoRefresh(callback, intervalMs = 5000) {
|
stopAutoRefresh();
|
callback(); // Initial call
|
refreshInterval = setInterval(callback, intervalMs);
|
}
|
|
function stopAutoRefresh() {
|
if (refreshInterval) {
|
clearInterval(refreshInterval);
|
refreshInterval = null;
|
}
|
}
|
|
// Page unload handler
|
window.addEventListener('beforeunload', () => {
|
stopAutoRefresh();
|
});
|