page1.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. let cpuChart = null;
  2. let memChart = null;
  3. let diskChart = null;
  4. let sysStatusTimer = null;
  5. let resizeHandler = null;
  6. let page1Active = false;
  7. function getSystemInfo(){
  8. fetch("/api/system/info")
  9. .then(r=>{
  10. if(!r.ok) throw new Error("HTTP "+r.status);
  11. return r.json();
  12. })
  13. .then(d=>{
  14. cpuChart.setOption({
  15. graphic:[{
  16. type:"text",
  17. left:"center",
  18. top:"75%",
  19. style:{
  20. text:`${d.cpu_cores||"--"}核 ${d.cpu_freq||"--"}MHz 温度${d.cpu_temp||"--"}`,
  21. fill:"#aaa",
  22. fontSize:15
  23. }
  24. }],
  25. series:[{data:[{value:d.cpu_usage}]}]
  26. });
  27. memChart.setOption({
  28. graphic:[{
  29. type:"text",
  30. left:"center",
  31. top:"75%",
  32. style:{
  33. text:`${d.mem_used||"--"} / ${d.mem_total||"--"}`,
  34. fill:"#aaa",
  35. fontSize:15
  36. }
  37. }],
  38. series:[{data:[{value:d.mem_percent}]}]
  39. });
  40. diskChart.setOption({
  41. title:{
  42. text:`${d.disk_percent}%`,
  43. subtext:`${d.disk_used||"--"} / ${d.disk_total||"--"}`,
  44. left:"center",
  45. top:"38%",
  46. textStyle:{
  47. fontSize:38,
  48. fontWeight:"bold"
  49. },
  50. subtextStyle:{
  51. fontSize:15
  52. }
  53. },
  54. series:[{
  55. data:[
  56. {value:d.disk_percent,name:"已使用"},
  57. {value:100-d.disk_percent,name:"剩余"}
  58. ]
  59. }]
  60. });
  61. })
  62. .catch(e=>console.error("system info failed:",e));
  63. }
  64. function gaugeOption(){
  65. return {
  66. series:[{
  67. type:"gauge",
  68. radius:"95%",
  69. center:["50%","55%"],
  70. min:0,
  71. max:100,
  72. startAngle:210,
  73. endAngle:-30,
  74. axisLine:{
  75. lineStyle:{
  76. width:22
  77. }
  78. },
  79. progress:{
  80. show:true,
  81. width:22
  82. },
  83. pointer:{show:false},
  84. axisTick:{show:false},
  85. splitLine:{show:false},
  86. axisLabel:{show:false},
  87. detail:{
  88. fontSize:42,
  89. fontWeight:"bold",
  90. offsetCenter:[0,"0%"],
  91. formatter:"{value}%"
  92. },
  93. title:{show:false},
  94. data:[{value:0}]
  95. }]
  96. };
  97. }
  98. function getLoadInfo(){
  99. fetch("/api/system/loadAverage")
  100. .then(async r => {
  101. if (!r.ok) {
  102. throw new Error("HTTP " + r.status);
  103. }
  104. return r.json();
  105. })
  106. .then(data => {
  107. if(!page1Active){
  108. return;
  109. }
  110. document.getElementById("load1m").textContent = data.load1m || "--";
  111. document.getElementById("load5m").textContent = data.load5m || "--";
  112. document.getElementById("load15m").textContent = data.load15m || "--";
  113. document.getElementById("runQueue").textContent = data.runQueue || "--";
  114. document.getElementById("bootTime").textContent = data.bootTime || "--";
  115. document.getElementById("uptime").textContent = data.uptime || "--";
  116. })
  117. .catch(e => {
  118. if(!page1Active){
  119. return;
  120. }
  121. console.error("network status failed:", e);
  122. document.getElementById("load1m").textContent = "--";
  123. document.getElementById("load5m").textContent = "--";
  124. document.getElementById("load15m").textContent = "--";
  125. document.getElementById("runQueue").textContent = "--";
  126. document.getElementById("bootTime").textContent = "--";
  127. document.getElementById("uptime").textContent = "--";
  128. });
  129. }
  130. function getServiceInfo(){
  131. fetch("/api/system/serviceStatus")
  132. .then(r => {
  133. if (!r.ok) {
  134. throw new Error("HTTP " + r.status);
  135. }
  136. return r.json();
  137. })
  138. .then(data => {
  139. if(!page1Active){
  140. return;
  141. }
  142. document.getElementById("var1").textContent = data.var1 || "--";
  143. document.getElementById("var2").textContent = data.var2 || "--";
  144. document.getElementById("var3").textContent = data.var3 || "--";
  145. document.getElementById("var4").textContent = data.var4 || "--";
  146. document.getElementById("var5").textContent = data.var5 || "--";
  147. document.getElementById("var6").textContent = data.var6 || "--";
  148. document.getElementById("var7").textContent = data.var7 || "--";
  149. document.getElementById("var8").textContent = data.var8 || "--";
  150. document.getElementById("var11").textContent = data.var11 || "--";
  151. document.getElementById("var22").textContent = data.var22 || "--";
  152. document.getElementById("var33").textContent = data.var33 || "--";
  153. document.getElementById("var44").textContent = data.var44 || "--";
  154. document.getElementById("var55").textContent = data.var55 || "--";
  155. document.getElementById("var66").textContent = data.var66 || "--";
  156. document.getElementById("var77").textContent = data.var77 || "--";
  157. document.getElementById("var88").textContent = data.var88 || "--";
  158. })
  159. .catch(e => {
  160. if(!page1Active){
  161. return;
  162. }
  163. console.error("getAllServiceStatus() failed:", e);
  164. document.getElementById("var1").textContent = "--";
  165. document.getElementById("var2").textContent = "--";
  166. document.getElementById("var3").textContent = "--";
  167. document.getElementById("var4").textContent = "--";
  168. document.getElementById("var5").textContent = "--";
  169. document.getElementById("var6").textContent = "--";
  170. document.getElementById("var7").textContent = "--";
  171. document.getElementById("var8").textContent = "--";
  172. document.getElementById("var11").textContent = "--";
  173. document.getElementById("var22").textContent = "--";
  174. document.getElementById("var33").textContent = "--";
  175. document.getElementById("var44").textContent = "--";
  176. document.getElementById("var55").textContent = "--";
  177. document.getElementById("var66").textContent = "--";
  178. document.getElementById("var77").textContent = "--";
  179. document.getElementById("var88").textContent = "--";
  180. });
  181. }
  182. function startSysStatusRefresh(){
  183. if(sysStatusTimer) return;
  184. getSystemInfo();
  185. getLoadInfo();
  186. getServiceInfo();
  187. sysStatusTimer = setInterval(() => {
  188. getSystemInfo();
  189. getLoadInfo();
  190. getServiceInfo();
  191. }, 5000);
  192. }
  193. function stopSysStatusRefresh(){
  194. if(sysStatusTimer){
  195. clearInterval(sysStatusTimer);
  196. sysStatusTimer=null;
  197. }
  198. }
  199. function resizeSysCharts(){
  200. cpuChart?.resize();
  201. memChart?.resize();
  202. diskChart?.resize();
  203. }
  204. const serviceNames = {
  205. "yfkj-networkd.service": "设备自动联网",
  206. "yfkj-timesyncd.service": "系统时间同步",
  207. "yfkj-gnss.service": "地理坐标定位",
  208. "yfkj-camera-capture.service": "相机图像采集",
  209. "yfkj-sshd-mqtt-bridge.service": "远程运维通道",
  210. "yfkj-app-install.service": "应用安装卸载",
  211. "yfkj-web-ui.service": "统一配置管理",
  212. "yfkj-upgrade.service": "开机自动升级",
  213. };
  214. function switchServiceVersion(service, action)
  215. {
  216. let name = serviceNames[service] || service;
  217. let msg = action === "factory"
  218. ? `确认将【${name}】恢复到出厂版本吗?\n\n警告: 切换过程中服务会自动重启,请勿断开电源!`
  219. : `确认将【${name}】回退到上一版本吗?\n\n警告: 切换过程中服务会自动重启,请勿断开电源!`;
  220. if(!confirm(msg)){
  221. return;
  222. }
  223. let password = prompt("请输入操作密码:");
  224. if(password === null){
  225. return;
  226. }
  227. password = password.trim();
  228. fetch("/api/service/version/switch", {
  229. method:"POST",
  230. headers:{
  231. "Content-Type":"application/json"
  232. },
  233. body:JSON.stringify({
  234. service:service,
  235. action:action,
  236. password:password
  237. })
  238. })
  239. .then(r=>r.json())
  240. .then(d=>{
  241. alert(`【${name}】\n\n${d.status=="ok" ? "✅ 版本切换成功" : "❌ 版本切换失败:" + d.message}`);
  242. })
  243. .catch(e=>{
  244. alert(`【${name}】\n\n❌ 请求失败:${e.message}`);
  245. });
  246. }
  247. function switchAutoUpgrade(action)
  248. {
  249. let msg = action === "enable"
  250. ? "确认要打开 【开机自动升级】 吗?"
  251. : "确认要关闭 【开机自动升级】 吗?";
  252. if(!confirm(msg)){
  253. return;
  254. }
  255. let password = prompt("请输入操作密码:");
  256. if(password === null){
  257. return;
  258. }
  259. password = password.trim();
  260. fetch("/api/upgrade/on-off", {
  261. method:"POST",
  262. headers:{
  263. "Content-Type":"application/json"
  264. },
  265. body:JSON.stringify({
  266. action:action,
  267. password:password
  268. })
  269. })
  270. .then(r=>r.json())
  271. .then(d=>{
  272. alert(`【开机自动升级】\n\n${d.status=="ok" ? (action=="enable" ? "✅ 已打开" : "✅ 已关闭") : "❌ 操作失败: " + d.message}`);
  273. })
  274. .catch(e=>{
  275. alert(`【开机自动升级】\n\n❌ 请求失败: ${e.message}`);
  276. });
  277. }
  278. function initPage1(){
  279. page1Active = true;
  280. cpuChart=echarts.init(document.getElementById("cpu-chart"));
  281. memChart=echarts.init(document.getElementById("mem-chart"));
  282. diskChart=echarts.init(document.getElementById("disk-chart"));
  283. cpuChart.setOption(gaugeOption());
  284. memChart.setOption(gaugeOption());
  285. diskChart.setOption({
  286. title:{
  287. text:"0%",
  288. subtext:"-- / --",
  289. left:"center",
  290. top:"38%",
  291. textStyle:{
  292. fontSize:38,
  293. fontWeight:"bold"
  294. },
  295. subtextStyle:{
  296. fontSize:15
  297. }
  298. },
  299. series:[{
  300. type:"pie",
  301. radius:["65%","85%"],
  302. label:{show:false},
  303. data:[
  304. {value:0,name:"已使用"},
  305. {value:100,name:"剩余"}
  306. ]
  307. }]
  308. });
  309. startSysStatusRefresh();
  310. resizeHandler = resizeSysCharts;
  311. window.addEventListener(
  312. "resize",
  313. resizeHandler
  314. );
  315. setTimeout(()=>{
  316. resizeSysCharts();
  317. },100);
  318. }
  319. function exitPage1(){
  320. page1Active = false;
  321. stopSysStatusRefresh();
  322. if(resizeHandler){
  323. window.removeEventListener(
  324. "resize",
  325. resizeHandler
  326. );
  327. resizeHandler=null;
  328. }
  329. cpuChart?.dispose();
  330. memChart?.dispose();
  331. diskChart?.dispose();
  332. cpuChart=null;
  333. memChart=null;
  334. diskChart=null;
  335. }