PAU.html 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>设备组态图 - {{ .deviceName }}</title>
  6. <style>
  7. body {
  8. font-family: Arial, sans-serif;
  9. background-color: #f4f6f8;
  10. padding: 20px;
  11. }
  12. h1 {
  13. text-align: center;
  14. color: #333;
  15. }
  16. .dashboard {
  17. display: grid;
  18. grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  19. gap: 20px;
  20. }
  21. .card {
  22. background: white;
  23. border-radius: 8px;
  24. box-shadow: 0 2px 6px rgba(0,0,0,0.1);
  25. padding: 20px;
  26. }
  27. .card h3 {
  28. margin-top: 0;
  29. font-size: 1.2em;
  30. color: #555;
  31. }
  32. .value {
  33. font-size: 1.5em;
  34. font-weight: bold;
  35. color: #007bff;
  36. margin-top: 10px;
  37. }
  38. .status-on {
  39. color: green;
  40. }
  41. .status-off {
  42. color: red;
  43. }
  44. </style>
  45. </head>
  46. <body>
  47. <h1>{{ .deviceName }} 组态图</h1>
  48. <div class="dashboard" id="dashboard">
  49. <!-- 动态生成卡片 -->
  50. </div>
  51. <script>
  52. const deviceName = "{{ .deviceName }}";
  53. const eventSource = new EventSource(`./pointSSE?deviceName=${deviceName}`);
  54. const dashboard = document.getElementById("dashboard");
  55. // 初始化卡片 DOM 结构
  56. const fields = {
  57. "冬夏季模式": { type: "text", label: "冬夏模式" },
  58. "回风二氧化碳": { type: "number", unit: "ppm", label: "回风 CO₂" },
  59. "回风温度": { type: "number", unit: "℃", label: "回风温度" },
  60. "回风阀反馈": { type: "number", unit: "%", label: "回风阀开度" },
  61. "故障报警": { type: "boolean", label: "故障报警" },
  62. "新风温度": { type: "number", unit: "℃", label: "新风温度" },
  63. "新风阀反馈": { type: "number", unit: "%", label: "新风阀开度" },
  64. "水阀反馈": { type: "number", unit: "%", label: "水阀开度" },
  65. "自动状态": { type: "boolean", label: "自动状态" },
  66. "过滤网压差": { type: "boolean", label: "过滤网压差" },
  67. "运行状态": { type: "boolean", label: "运行状态" },
  68. "送风温度": { type: "number", unit: "℃", label: "送风温度" },
  69. "送风湿度": { type: "number", unit: "%", label: "送风湿度" },
  70. "防冻开关": { type: "boolean", label: "防冻开关" },
  71. "风机压差": { type: "boolean", label: "风机压差" }
  72. };
  73. // 创建初始卡片
  74. function createCards() {
  75. Object.keys(fields).forEach(key => {
  76. const card = document.createElement("div");
  77. card.className = "card";
  78. card.id = `card-${key}`;
  79. card.innerHTML = `
  80. <h3>${fields[key].label}</h3>
  81. <div class="value" id="value-${key}">--</div>
  82. `;
  83. dashboard.appendChild(card);
  84. });
  85. }
  86. createCards();
  87. // 处理 SSE 数据更新
  88. eventSource.onmessage = function(event) {
  89. try {
  90. const data = JSON.parse(event.data)?.data || {};
  91. for (const key in data) {
  92. const value = data[key];
  93. const el = document.getElementById(`value-${key}`);
  94. if (!el) continue;
  95. // 类型判断并格式化显示
  96. const field = fields[key];
  97. if (field?.type === 'boolean') {
  98. el.textContent = value === "是" ? "是" : "否";
  99. el.className = `value ${value === "是" ? "status-on" : "status-off"}`;
  100. } else if (field?.type === 'number') {
  101. el.textContent = `${parseFloat(value).toFixed(2)}${field.unit || ''}`;
  102. el.className = "value"; // 修复此处
  103. } else {
  104. el.textContent = value;
  105. el.className = "value"; // 保持一致性
  106. }
  107. }
  108. } catch (e) {
  109. console.error("解析数据失败", e);
  110. }
  111. };
  112. eventSource.onerror = function(err) {
  113. console.error("SSE 错误:", err);
  114. };
  115. </script>
  116. </body>
  117. </html>