page1.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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("var9").textContent = data.var9 || "--";
  151. document.getElementById("var11").textContent = data.var11 || "--";
  152. document.getElementById("var22").textContent = data.var22 || "--";
  153. document.getElementById("var33").textContent = data.var33 || "--";
  154. document.getElementById("var44").textContent = data.var44 || "--";
  155. document.getElementById("var55").textContent = data.var55 || "--";
  156. document.getElementById("var66").textContent = data.var66 || "--";
  157. document.getElementById("var77").textContent = data.var77 || "--";
  158. document.getElementById("var88").textContent = data.var88 || "--";
  159. })
  160. .catch(e => {
  161. if(!page1Active){
  162. return;
  163. }
  164. console.error("getAllServiceStatus() failed:", e);
  165. document.getElementById("var1").textContent = "--";
  166. document.getElementById("var2").textContent = "--";
  167. document.getElementById("var3").textContent = "--";
  168. document.getElementById("var4").textContent = "--";
  169. document.getElementById("var5").textContent = "--";
  170. document.getElementById("var6").textContent = "--";
  171. document.getElementById("var7").textContent = "--";
  172. document.getElementById("var8").textContent = "--";
  173. document.getElementById("var9").textContent = "--";
  174. document.getElementById("var11").textContent = "--";
  175. document.getElementById("var22").textContent = "--";
  176. document.getElementById("var33").textContent = "--";
  177. document.getElementById("var44").textContent = "--";
  178. document.getElementById("var55").textContent = "--";
  179. document.getElementById("var66").textContent = "--";
  180. document.getElementById("var77").textContent = "--";
  181. document.getElementById("var88").textContent = "--";
  182. });
  183. }
  184. function startSysStatusRefresh(){
  185. if(sysStatusTimer) return;
  186. getSystemInfo();
  187. getLoadInfo();
  188. getServiceInfo();
  189. sysStatusTimer = setInterval(() => {
  190. getSystemInfo();
  191. getLoadInfo();
  192. getServiceInfo();
  193. }, 5000);
  194. }
  195. function stopSysStatusRefresh(){
  196. if(sysStatusTimer){
  197. clearInterval(sysStatusTimer);
  198. sysStatusTimer=null;
  199. }
  200. }
  201. function resizeSysCharts(){
  202. cpuChart?.resize();
  203. memChart?.resize();
  204. diskChart?.resize();
  205. }
  206. const serviceNames = {
  207. "yfkj-networkd.service": "设备自动联网",
  208. "yfkj-timesyncd.service": "系统时间同步",
  209. "yfkj-gnss.service": "地理坐标定位",
  210. "yfkj-camera-capture.service": "相机图像采集",
  211. "yfkj-sshd-mqtt-bridge.service": "远程运维通道",
  212. "yfkj-app-install.service": "应用安装卸载",
  213. "yfkj-web-ui.service": "统一配置管理",
  214. "yfkj-upgrade.service": "开机自动升级",
  215. };
  216. function switchServiceVersion(service, action)
  217. {
  218. let name = serviceNames[service] || service;
  219. let msg = action === "factory"
  220. ? `确认将【${name}】恢复到出厂版本吗?\n\n警告: 切换过程中服务会自动重启,请勿断开电源!`
  221. : `确认将【${name}】回退到上一版本吗?\n\n警告: 切换过程中服务会自动重启,请勿断开电源!`;
  222. if(!confirm(msg)){
  223. return;
  224. }
  225. let password = prompt("请输入操作密码:");
  226. if(password === null){
  227. return;
  228. }
  229. password = password.trim();
  230. fetch("/api/service/version/switch", {
  231. method:"POST",
  232. headers:{
  233. "Content-Type":"application/json"
  234. },
  235. body:JSON.stringify({
  236. service:service,
  237. action:action,
  238. password:password
  239. })
  240. })
  241. .then(r=>r.json())
  242. .then(d=>{
  243. alert(`【${name}】\n\n${d.status=="ok" ? "✅ 版本切换成功" : "❌ 版本切换失败:" + d.message}`);
  244. })
  245. .catch(e=>{
  246. alert(`【${name}】\n\n❌ 请求失败:${e.message}`);
  247. });
  248. }
  249. function switchAutoUpgrade(action)
  250. {
  251. let msg = action === "enable"
  252. ? "确认要打开 【开机自动升级】 吗?"
  253. : "确认要关闭 【开机自动升级】 吗?";
  254. if(!confirm(msg)){
  255. return;
  256. }
  257. let password = prompt("请输入操作密码:");
  258. if(password === null){
  259. return;
  260. }
  261. password = password.trim();
  262. fetch("/api/upgrade/on-off", {
  263. method:"POST",
  264. headers:{
  265. "Content-Type":"application/json"
  266. },
  267. body:JSON.stringify({
  268. action:action,
  269. password:password
  270. })
  271. })
  272. .then(r=>r.json())
  273. .then(d=>{
  274. alert(`【开机自动升级】\n\n${d.status=="ok" ? (action=="enable" ? "✅ 已打开" : "✅ 已关闭") : "❌ 操作失败: " + d.message}`);
  275. })
  276. .catch(e=>{
  277. alert(`【开机自动升级】\n\n❌ 请求失败: ${e.message}`);
  278. });
  279. }
  280. function initPage1(){
  281. page1Active = true;
  282. cpuChart=echarts.init(document.getElementById("cpu-chart"));
  283. memChart=echarts.init(document.getElementById("mem-chart"));
  284. diskChart=echarts.init(document.getElementById("disk-chart"));
  285. cpuChart.setOption(gaugeOption());
  286. memChart.setOption(gaugeOption());
  287. diskChart.setOption({
  288. title:{
  289. text:"0%",
  290. subtext:"-- / --",
  291. left:"center",
  292. top:"38%",
  293. textStyle:{
  294. fontSize:38,
  295. fontWeight:"bold"
  296. },
  297. subtextStyle:{
  298. fontSize:15
  299. }
  300. },
  301. series:[{
  302. type:"pie",
  303. radius:["65%","85%"],
  304. label:{show:false},
  305. data:[
  306. {value:0,name:"已使用"},
  307. {value:100,name:"剩余"}
  308. ]
  309. }]
  310. });
  311. startSysStatusRefresh();
  312. resizeHandler = resizeSysCharts;
  313. window.addEventListener(
  314. "resize",
  315. resizeHandler
  316. );
  317. setTimeout(()=>{
  318. resizeSysCharts();
  319. },100);
  320. }
  321. function exitPage1(){
  322. page1Active = false;
  323. stopSysStatusRefresh();
  324. if(resizeHandler){
  325. window.removeEventListener(
  326. "resize",
  327. resizeHandler
  328. );
  329. resizeHandler=null;
  330. }
  331. cpuChart?.dispose();
  332. memChart?.dispose();
  333. diskChart?.dispose();
  334. cpuChart=null;
  335. memChart=null;
  336. diskChart=null;
  337. }