Home.razor 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. @page "/"
  2. @rendermode InteractiveServer
  3. @using BlazorWeb1.Models
  4. @using BlazorWeb1.Server
  5. @using System.Timers
  6. @inject PizzaService PizzaSvc
  7. @inject NavigationManager Navigation
  8. @* @inject UdpListenerService us *@
  9. <head>
  10. <meta charset="utf-8" />
  11. @* <link href="css/site.css" rel="stylesheet" /> *@
  12. <title>Blazing Pizza</title>
  13. </head>
  14. <div class="main">
  15. <div class="container">
  16. <div class="nozzle-content">
  17. <div class="grid-container">
  18. @{
  19. int i = 0;
  20. foreach (var item in items)
  21. {
  22. i++;
  23. int num_page = ShowNozzleItem_Row * ShowNozzle_Col;
  24. if (i >= currentPage * num_page+1 && i <= (currentPage + 1) * num_page)
  25. {
  26. <div class="grid-item">
  27. <Nozzle BottomText=""
  28. warnstate="@item.Value.warnstate"
  29. NozNo="@item.Value.noz.ToString()"
  30. VLR="@item.Value.VLR"
  31. nozzlestate="@item.Value.nozzlestate"
  32. OilName="@item.Value.oil" />
  33. </div>
  34. }
  35. }
  36. }
  37. </div>
  38. </div>
  39. </div>
  40. <PageSwitcher CurrentPage="@currentPage"
  41. PageChanged="OnPageChanged" />
  42. <div class="infoctainer">
  43. <div class="sensorcontainer">
  44. <!-- 传感器按钮网格 -->
  45. <div class="button-row">
  46. <SensorButton SensorName="油罐压力"
  47. AlertLevel="@alertLevels["oilTankPressure"]"
  48. OnClick="@(() => ShowDetailModal("oilTankPressure"))" />
  49. <SensorButton SensorName="浓度信息"
  50. AlertLevel="@alertLevels["concentrationInfo"]"
  51. OnClick="@(() => ShowDetailModal("concentrationInfo"))" />
  52. </div>
  53. <div class="button-row">
  54. <SensorButton SensorName="管线压力"
  55. AlertLevel="@alertLevels["pipelinePressure"]"
  56. OnClick="@(() => ShowDetailModal("pipelinePressure"))" />
  57. <SensorButton SensorName="油罐温度"
  58. AlertLevel="@alertLevels["oilTankTemperature"]"
  59. OnClick="@(() => ShowDetailModal("oilTankTemperature"))" />
  60. </div>
  61. <!-- 详细信息模态框 -->
  62. @if (showModal)
  63. {
  64. <Modal Title="BasicModal"
  65. Style="top: 20px"
  66. @bind-Visible="@_visible_sensordetail">
  67. <SensorDetailModal SensorType="@selectedSensor"
  68. SensorData="@sensorData[selectedSensor]"
  69. OnClose="@CloseModal" />
  70. </Modal>
  71. }
  72. </div>
  73. <div class="remoteinfocontainer">
  74. <div class="button-row">
  75. <button class="info-button">北京</button>
  76. <button class ="info-button-state"> 不开启上传</button>
  77. </div>
  78. <div class="button-row">
  79. <button class="info-button">无设置</button>
  80. <button class="info-button-state"> 不开启上传</button>
  81. </div>
  82. <div class="button-row">
  83. <button class="info-button">无设置</button>
  84. <button class="info-button-state"> 不开启上传</button>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. @code {
  90. private Dictionary<string, int> alertLevels = new Dictionary<string, int>
  91. {
  92. ["oilTankPressure"] = 0,
  93. ["concentrationInfo"] = 0,
  94. ["pipelinePressure"] = 0,
  95. ["oilTankTemperature"] = 0
  96. };
  97. private bool showModal = false;
  98. private string selectedSensor = "";
  99. bool _visible_sensordetail = false;
  100. // 示例传感器数据
  101. private Dictionary<string, List<SensorRecord>> sensorData = new Dictionary<string, List<SensorRecord>>
  102. {
  103. ["oilTankPressure"] = new List<SensorRecord>
  104. {
  105. new SensorRecord { Sensor = "PT-101A", Value = "2.5 MPa", Status = 0, Message = "正常" },
  106. new SensorRecord { Sensor = "PT-101B", Value = "2.3 MPa", Status = 1, Message = "轻微波动" },
  107. new SensorRecord { Sensor = "PT-102", Value = "2.7 MPa", Status = 2, Message = "高压预警" }
  108. },
  109. ["concentrationInfo"] = new List<SensorRecord>
  110. {
  111. new SensorRecord { Sensor = "CT-201", Value = "85%", Status = 0, Message = "正常" },
  112. new SensorRecord { Sensor = "CT-202", Value = "87%", Status = 1, Message = "接近上限" },
  113. new SensorRecord { Sensor = "CT-203", Value = "92%", Status = 2, Message = "浓度过高" }
  114. },
  115. ["pipelinePressure"] = new List<SensorRecord>
  116. {
  117. new SensorRecord { Sensor = "PL-301", Value = "3.2 MPa", Status = 0, Message = "正常" },
  118. new SensorRecord { Sensor = "PL-302", Value = "3.0 MPa", Status = 0, Message = "稳定" },
  119. new SensorRecord { Sensor = "PL-303", Value = "3.8 MPa", Status = 2, Message = "超压警报" }
  120. },
  121. ["oilTankTemperature"] = new List<SensorRecord>
  122. {
  123. new SensorRecord { Sensor = "TT-401", Value = "45°C", Status = 0, Message = "正常" },
  124. new SensorRecord { Sensor = "TT-402", Value = "52°C", Status = 1, Message = "温度升高" },
  125. new SensorRecord { Sensor = "TT-403", Value = "68°C", Status = 2, Message = "高温警告" }
  126. }
  127. };
  128. private void HandleAlertChange(string sensorType, int level)
  129. {
  130. alertLevels[sensorType] = level;
  131. StateHasChanged();
  132. }
  133. private void ShowDetailModal(string sensorType)
  134. {
  135. selectedSensor = sensorType;
  136. showModal = true;
  137. _visible_sensordetail = true;
  138. }
  139. private void CloseModal()
  140. {
  141. showModal = false;
  142. selectedSensor = "";
  143. }
  144. public class SensorRecord
  145. {
  146. public string Sensor { get; set; }
  147. public string Value { get; set; }
  148. public int Status { get; set; }
  149. public string Message { get; set; }
  150. }
  151. }
  152. @code {
  153. private Dictionary<int, NozzleState> items = new Dictionary<int, NozzleState>();
  154. private const int ShowNozzleItem_Row = 8;//每行显示的枪数
  155. private const int ShowNozzle_Col = 4;//每页显示的行数
  156. int totalpage = 0;
  157. int currentPage = 0;
  158. private void OnPageChanged(int pageIndex)
  159. {
  160. currentPage = pageIndex;
  161. }
  162. private Timer timer;
  163. private bool isAutoRefreshEnabled = true;
  164. private DateTime lastUpdateTime = DateTime.Now;
  165. protected override async Task OnInitializedAsync()
  166. {
  167. await RefreshData();
  168. StartTimer();
  169. }
  170. private void StartTimer()
  171. {
  172. timer = new Timer(1000); // 1秒间隔
  173. timer.Elapsed += async (sender, e) => await RefreshData();
  174. timer.Start();
  175. }
  176. private async Task RefreshData()
  177. {
  178. var nozzlestates = GlobalTool.g_mNozzleState;//us.GetNozzleState();
  179. try
  180. {
  181. // 更新UI
  182. await InvokeAsync(() =>
  183. {
  184. items = nozzlestates;// mockData;
  185. lastUpdateTime = DateTime.Now;
  186. StateHasChanged();
  187. });
  188. }
  189. catch (Exception ex)
  190. {
  191. Console.WriteLine($"数据刷新失败: {ex.Message}");
  192. }
  193. }
  194. private void ToggleAutoRefresh()
  195. {
  196. isAutoRefreshEnabled = !isAutoRefreshEnabled;
  197. if (isAutoRefreshEnabled)
  198. {
  199. StartTimer();
  200. }
  201. else
  202. {
  203. timer?.Stop();
  204. }
  205. }
  206. public void Dispose()
  207. {
  208. timer?.Stop();
  209. timer?.Dispose();
  210. }
  211. public class NozzleData
  212. {
  213. public string IconUrl { get; set; }
  214. public string Title { get; set; }
  215. public string Description { get; set; }
  216. public int warnstate { get; set; }
  217. public string Line1 { get; set; }
  218. public string Line2 { get; set; }
  219. public string Line3 { get; set; }
  220. }
  221. }
  222. <style>
  223. .main {
  224. background-color: white;
  225. }
  226. .container {
  227. padding: 5px;
  228. font-family: Arial, sans-serif;
  229. background-color: white;
  230. }
  231. .nozzle-content {
  232. grid-area: main;
  233. padding: 5px;
  234. overflow-y: auto;
  235. /* 固定主要内容区域大小 */
  236. /* width: calc(100vw - 250px);
  237. height: calc(100vh - 110px); */
  238. width:950px;
  239. height: 340px;
  240. border-radius: 6px;
  241. border: 1px solid lightblue;
  242. }
  243. .grid-container {
  244. display: grid;
  245. grid-template-columns: repeat(8, 1fr);
  246. gap: 5px;
  247. margin-top: 5px;
  248. }
  249. .grid-item {
  250. background-color: #f0f8ff;
  251. border: 1px solid #b0e0e6;
  252. border-radius: 5px;
  253. padding: 5px;
  254. text-align: center;
  255. /* min-height: 60px; */
  256. display: flex;
  257. align-items: center;
  258. justify-content: center;
  259. }
  260. .infoctainer {
  261. display: flex;
  262. margin-top: 10px;
  263. flex-direction: row;
  264. gap: 5px;
  265. padding: 10px;
  266. background-color: lightblue
  267. }
  268. .sensorcontainer {
  269. display: flex;
  270. flex-direction: column;
  271. gap: 5px;
  272. padding: 10px;
  273. background-color:lightblue
  274. }
  275. .remoteinfocontainer {
  276. display: flex;
  277. flex-direction: column;
  278. gap: 5px;
  279. padding: 10px;
  280. background-color: lightblue
  281. }
  282. .button-row {
  283. display: flex;
  284. gap: 5px;
  285. }
  286. .custom-button {
  287. padding: 5px 10px;
  288. border: none;
  289. width:150px;
  290. height:50px;
  291. border-radius: 8px;
  292. font-size: 16px;
  293. cursor: pointer;
  294. transition: transform 0.2s ease, box-shadow 0.2s ease;
  295. }
  296. .info-button {
  297. border: none;
  298. width: 80px;
  299. height: 40px;
  300. font-size: 16px;
  301. cursor: pointer;
  302. background: lightblue;
  303. }
  304. .info-button-state {
  305. border: none;
  306. width: 120px;
  307. height: 40px;
  308. font-size: 16px;
  309. cursor: pointer;
  310. background: lightblue;
  311. }
  312. .custom-button:hover {
  313. transform: translateY(-2px);
  314. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  315. }
  316. .green {
  317. background-color: #4CAF50;
  318. color: white;
  319. }
  320. .yellow {
  321. background-color: #FFEB3B;
  322. color: black;
  323. }
  324. .red {
  325. background-color: #F44336;
  326. color: white;
  327. }
  328. .default {
  329. background-color: #e0e0e0;
  330. color: black;
  331. }
  332. </style>
  333. @* <style>
  334. .gridrow
  335. {
  336. background-color: aqua;
  337. border-color: #1861ac;
  338. }
  339. #components-grid-demo-playground [class~='ant-col'] {
  340. background: transparent;
  341. border: 0;
  342. }
  343. #components-grid-demo-playground [class~='ant-col'] > div {
  344. height: 120px;
  345. font-size: 14px;
  346. line-height: 120px;
  347. background: #0092ff;
  348. border-radius: 4px;
  349. }
  350. #components-grid-demo-playground pre {
  351. padding: 8px 16px;
  352. font-size: 13px;
  353. background: #f9f9f9;
  354. border-radius: 6px;
  355. }
  356. #components-grid-demo-playground pre.demo-code {
  357. direction: ltr;
  358. }
  359. #components-grid-demo-playground .ant-col {
  360. padding: 0;
  361. }
  362. </style> *@
  363. @*
  364. <table>
  365. <thead>
  366. <tr>
  367. <th>Pizza Name</th>
  368. <th>Description</th>
  369. <th>Vegetarian?</th>
  370. <th>Vegan?</th>
  371. <th>Price</th>
  372. </tr>
  373. </thead>
  374. <tbody>
  375. @foreach (var pizza in todaysPizzas)
  376. {
  377. <tr >
  378. <td>@pizza.Name <CascadingValue Value="NickName"><Child Message=@pizza.Name> </Child></CascadingValue></td>
  379. <td>@pizza.Description</td>
  380. <td>@pizza.Vegetarian</td>
  381. <td>@pizza.Vegan</td>
  382. <td>@pizza.Price</td>
  383. </tr>
  384. }
  385. </tbody>
  386. </table> *@
  387. @* <ul class="pizza-cards">
  388. @if (specials != null)
  389. {
  390. @foreach (var special in specials)
  391. {
  392. <li class="image-item" style="background-image: url('@special.ImageUrl')">
  393. <div class="pizza-info">
  394. <span class="title">@special.Name</span>
  395. @special.Description
  396. <span class="price">@special.GetFormattedBasePrice()</span>
  397. </div>
  398. </li>
  399. }
  400. }
  401. </ul> *@
  402. @code {
  403. string NickName = "ES";
  404. private Pizza[] todaysPizzas;
  405. // protected override async Task OnInitializedAsync()
  406. // {
  407. // todaysPizzas = PizzaSvc.GetPizzasAsync();
  408. // }
  409. List<PizzaSpecial> specials = new();
  410. // protected override void OnInitialized()
  411. // {
  412. // specials.AddRange(new List<PizzaSpecial>
  413. // {
  414. // new PizzaSpecial { Name = "The Baconatorizor", BasePrice = 11.99M, Description = "It has EVERY kind of bacon", ImageUrl="img/pizzas/bacon.jpg"},
  415. // new PizzaSpecial { Name = "Buffalo chicken", BasePrice = 12.75M, Description = "Spicy chicken, hot sauce, and blue cheese, guaranteed to warm you up", ImageUrl="img/pizzas/meaty.jpg"},
  416. // new PizzaSpecial { Name = "Veggie Delight", BasePrice = 11.5M, Description = "It's like salad, but on a pizza", ImageUrl="img/pizzas/salad.jpg"},
  417. // new PizzaSpecial { Name = "Margherita", BasePrice = 9.99M, Description = "Traditional Italian pizza with tomatoes and basil", ImageUrl="img/pizzas/margherita.jpg"},
  418. // new PizzaSpecial { Name = "Basic Cheese Pizza", BasePrice = 11.99M, Description = "It's cheesy and delicious. Why wouldn't you want one?", ImageUrl="img/pizzas/cheese.jpg"},
  419. // new PizzaSpecial { Name = "Classic pepperoni", BasePrice = 10.5M, Description = "It's the pizza you grew up with, but Blazing hot!", ImageUrl="img/pizzas/pepperoni.jpg" }
  420. // });
  421. // }
  422. }