From d216edd0e9931d71664f33e625cff6d8131a0fad Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 13 三月 2026 16:00:40 +0800
Subject: [PATCH] 重构: 实现前后端分离架构
---
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js | 198 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 197 insertions(+), 1 deletions(-)
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js
index ac49c18..7cecf88 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js
@@ -1,4 +1,200 @@
锘�// 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.
-// Write your JavaScript code.
+// 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();
+});
--
Gitblit v1.9.3