repair-screen.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. (function ($, window) {
  2. "use strict";
  3. var config = window.repairScreenConfig || {};
  4. var state = {
  5. items: [],
  6. currentPage: 0,
  7. totalPages: 0,
  8. carouselTimer: null,
  9. refreshTimer: null
  10. };
  11. function pad(num) {
  12. return num < 10 ? "0" + num : String(num);
  13. }
  14. function updateClock() {
  15. var now = new Date();
  16. var text = now.getFullYear() + "-" + pad(now.getMonth() + 1) + "-" + pad(now.getDate()) +
  17. " " + pad(now.getHours()) + ":" + pad(now.getMinutes()) + ":" + pad(now.getSeconds());
  18. $("#screenTime").text(text);
  19. }
  20. function escapeHtml(text) {
  21. return String(text == null ? "" : text)
  22. .replace(/&/g, "&amp;")
  23. .replace(/</g, "&lt;")
  24. .replace(/>/g, "&gt;")
  25. .replace(/"/g, "&quot;");
  26. }
  27. function stateClass(stateCode) {
  28. if (stateCode === "1") {
  29. return "is-pending";
  30. }
  31. if (stateCode === "2") {
  32. return "is-repairing";
  33. }
  34. if (stateCode === "3") {
  35. return "is-done";
  36. }
  37. if (stateCode === "4") {
  38. return "is-fail";
  39. }
  40. return "is-other";
  41. }
  42. function renderSummary(summary) {
  43. summary = summary || {};
  44. $("#pendingCount").text(summary.pending || 0);
  45. $("#repairingCount").text(summary.repairing || 0);
  46. $("#todayDoneCount").text(summary.todayDone || 0);
  47. $("#todayFailCount").text(summary.todayFail || 0);
  48. }
  49. function renderPage(pageIndex, animate) {
  50. var pageSize = config.pageSize || 7;
  51. var start = pageIndex * pageSize;
  52. var pageData = state.items.slice(start, start + pageSize);
  53. var html = "";
  54. if (!pageData.length) {
  55. html = '<tr class="empty-row"><td colspan="9">暂无待处理返修数据</td></tr>';
  56. } else {
  57. pageData.forEach(function (item, index) {
  58. var seq = start + index + 1;
  59. html += "<tr>" +
  60. '<td class="col-seq">' + seq + "</td>" +
  61. '<td class="col-sn">' + escapeHtml(item.sn) + "</td>" +
  62. '<td class="col-oprno">' + escapeHtml(item.oprno || "--") + "</td>" +
  63. '<td class="col-item">' + escapeHtml(item.itemTitle || "--") + "</td>" +
  64. '<td class="col-type">' + escapeHtml(item.typeText || "--") + "</td>" +
  65. '<td class="col-remark">' + escapeHtml(item.remark || "--") + "</td>" +
  66. '<td class="col-state"><span class="state-tag ' + stateClass(item.state) + '">' +
  67. escapeHtml(item.stateText || "--") + "</span></td>" +
  68. '<td class="col-user">' + escapeHtml(item.createBy || "--") + "</td>" +
  69. '<td class="col-time">' + escapeHtml(item.createDate || "--") + "</td>" +
  70. "</tr>";
  71. });
  72. }
  73. var $body = $("#repairBody");
  74. if (!animate) {
  75. $body.removeClass("is-fading").addClass("is-visible").html(html);
  76. return;
  77. }
  78. $body.removeClass("is-visible").addClass("is-fading");
  79. setTimeout(function () {
  80. $body.html(html);
  81. $body.removeClass("is-fading").addClass("is-visible");
  82. }, 450);
  83. }
  84. function updatePageIndicator() {
  85. state.totalPages = Math.max(1, Math.ceil(state.items.length / (config.pageSize || 7)));
  86. $("#pageIndicator").text("第 " + (state.currentPage + 1) + " / " + state.totalPages + " 页");
  87. }
  88. function startCarousel() {
  89. stopCarousel();
  90. if (state.totalPages <= 1) {
  91. return;
  92. }
  93. state.carouselTimer = setInterval(function () {
  94. state.currentPage++;
  95. if (state.currentPage >= state.totalPages) {
  96. state.currentPage = 0;
  97. }
  98. updatePageIndicator();
  99. renderPage(state.currentPage, true);
  100. }, config.carouselInterval || 8000);
  101. }
  102. function stopCarousel() {
  103. if (state.carouselTimer) {
  104. clearInterval(state.carouselTimer);
  105. state.carouselTimer = null;
  106. }
  107. }
  108. function applyData(payload) {
  109. payload = payload || {};
  110. renderSummary(payload.summary);
  111. state.items = $.isArray(payload.list) ? payload.list : [];
  112. state.currentPage = 0;
  113. updatePageIndicator();
  114. renderPage(0, false);
  115. startCarousel();
  116. }
  117. function showLoadError(message) {
  118. renderSummary({});
  119. state.items = [];
  120. state.currentPage = 0;
  121. updatePageIndicator();
  122. $("#repairBody").removeClass("is-fading").addClass("is-visible").html(
  123. '<tr class="empty-row"><td colspan="9">' + escapeHtml(message || "数据加载失败") + "</td></tr>"
  124. );
  125. stopCarousel();
  126. }
  127. function loadData() {
  128. var apiUrl = config.apiUrl;
  129. if (!apiUrl) {
  130. showLoadError("未配置数据接口");
  131. return;
  132. }
  133. $.ajax({
  134. url: apiUrl,
  135. type: "GET",
  136. dataType: "json",
  137. timeout: 20000
  138. }).done(function (res) {
  139. if (res && (res.result === "true" || res.result === true) && res.data) {
  140. applyData(res.data);
  141. scheduleRefresh(config.refreshInterval || 60000);
  142. } else {
  143. showLoadError((res && res.message) ? res.message : "接口返回异常");
  144. scheduleRefresh(5000);
  145. }
  146. }).fail(function (xhr) {
  147. var msg = "数据加载失败";
  148. if (xhr && xhr.status === 401) {
  149. msg = "接口未授权,请检查匿名访问配置";
  150. } else if (xhr && xhr.status === 404) {
  151. msg = "接口不存在,请确认服务已重启";
  152. } else if (xhr && (xhr.status === 0 || xhr.status >= 500)) {
  153. msg = "服务连接中,稍后自动重试…";
  154. } else if (xhr && xhr.status) {
  155. msg = "数据加载失败(HTTP " + xhr.status + ")";
  156. }
  157. // 保留上次成功数据,避免发版重启时大屏被清空
  158. if (!state.items.length) {
  159. showLoadError(msg);
  160. }
  161. scheduleRefresh(5000);
  162. });
  163. }
  164. function scheduleRefresh(delay) {
  165. if (state.refreshTimer) {
  166. clearTimeout(state.refreshTimer);
  167. }
  168. state.refreshTimer = setTimeout(loadData, delay || 60000);
  169. }
  170. function fitScreen() {
  171. var width = $(window).width();
  172. var height = $(window).height();
  173. var designWidth = 1920;
  174. var designHeight = 1080;
  175. var scale = Math.min(width / designWidth, height / designHeight);
  176. var marginLeft = (width - designWidth * scale) / 2;
  177. var marginTop = (height - designHeight * scale) / 2;
  178. $("body").css({
  179. transform: "scale(" + scale + ")",
  180. transformOrigin: "0 0",
  181. width: designWidth + "px",
  182. height: designHeight + "px",
  183. overflow: "hidden",
  184. marginLeft: marginLeft + "px",
  185. marginTop: marginTop + "px"
  186. });
  187. }
  188. function init() {
  189. $("#screenTitle").text(config.title || "返修区看板");
  190. updateClock();
  191. setInterval(updateClock, 1000);
  192. loadData();
  193. fitScreen();
  194. $(window).on("resize", fitScreen);
  195. }
  196. $(function () {
  197. init();
  198. });
  199. })(jQuery, window);