UnifiedSetting.razor 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. @page "/setting/unifiedsetting"
  2. @using EasyTemplate.Service
  3. @using EasyTemplate.Tool.Entity.App
  4. @using EasyTemplate.Page.Components.IdSelector
  5. @inject NozzleService nozzleService
  6. @inject IJSRuntime JSRuntime
  7. <div class="container-fluid">
  8. <div class="row">
  9. <!-- 油机列 -->
  10. <div class="col-md-3 border-end position-relative" style="height: calc(100vh - 100px);">
  11. <div class="d-flex justify-content-between align-items-center mb-3">
  12. <h5>油机列表</h5>
  13. <button class="btn btn-sm btn-primary" @onclick="ShowCreateEngineModal">
  14. <i class="fas fa-plus"></i>
  15. </button>
  16. </div>
  17. <!-- 显示所有油机选项 -->
  18. @* <div class="list-group mb-3">
  19. <button class="list-group-item list-group-item-action @(selectedEngineId == 0 ? "active" : "")"
  20. @onclick="() => SelectEngine(0)">
  21. 显示所有油机
  22. </button>
  23. </div> *@
  24. <!-- 油机列表 -->
  25. <div class="list-group flex-grow-1" style="max-height: 400px; overflow-y: auto; margin-bottom: 50px;">
  26. @if (paginatedEngines != null)
  27. {
  28. @foreach (var engine in paginatedEngines)
  29. {
  30. <div @onclick="() => SelectEngine(engine.EngineId)" class="list-group-item d-flex justify-content-between align-items-center py-1 @(selectedEngineId == engine.EngineId ? "active" : "")">
  31. <div style="cursor: pointer;">
  32. <div><strong>油机 @engine.EngineId</strong></div>
  33. </div>
  34. <div>
  35. <button class="btn btn-sm btn-info me-1 p-1" @onclick="() => ShowEditEngineModal(engine)">
  36. <i class="fas fa-edit"></i>
  37. </button>
  38. <button class="btn btn-sm btn-danger p-1" @onclick="() => DeleteEngine(engine.EngineId)">
  39. <i class="fas fa-trash"></i>
  40. </button>
  41. </div>
  42. </div>
  43. }
  44. }
  45. </div>
  46. <!-- 油机分页控件 -->
  47. @if (engines != null && engines.Count > pageSize)
  48. {
  49. <nav aria-label="油机分页" class="position-absolute" style="bottom: 50px; left: 0; right: 0;">
  50. <ul class="pagination pagination-sm justify-content-center mt-2 mb-0">
  51. <li class="page-item @(currentPage_Engine == 1 ? "disabled" : "")">
  52. <a class="page-link" @onclick="() => ChangePage_Engine(currentPage_Engine - 1)" tabindex="-1">上一页</a>
  53. </li>
  54. @for (int i = 1; i <= totalPages_Engine; i++)
  55. {
  56. var item = i;
  57. <li class="page-item @(currentPage_Engine == i ? "active" : "")">
  58. <a class="page-link" @onclick="() => ChangePage_Engine(item)">@item</a>
  59. </li>
  60. }
  61. <li class="page-item @(currentPage_Engine == totalPages_Engine ? "disabled" : "")">
  62. <a class="page-link" @onclick="() => ChangePage_Engine(currentPage_Engine + 1)">下一页</a>
  63. </li>
  64. </ul>
  65. </nav>
  66. }
  67. </div>
  68. <!-- 主板列 -->
  69. <div class="col-md-3 border-end position-relative" style="height: calc(100vh - 100px);">
  70. <div class="d-flex justify-content-between align-items-center mb-3">
  71. <h5>主板列表</h5>
  72. <button class="btn btn-sm btn-primary" @onclick="ShowCreateBoardModal" disabled="@(selectedEngineId == 0)">
  73. <i class="fas fa-plus"></i>
  74. </button>
  75. </div>
  76. @* <!-- 显示所有主板选项 -->
  77. <div class="list-group mb-3">
  78. <button class="list-group-item list-group-item-action @(selectedBoardId == 0 ? "active" : "")"
  79. @onclick="() => SelectBoard(0)" disabled="@(selectedEngineId == 0)">
  80. 显示所有主板
  81. </button>
  82. </div> *@
  83. <!-- 主板列表 -->
  84. <div class="list-group flex-grow-1" style="max-height: 400px; overflow-y: auto; margin-bottom: 50px;">
  85. @if (paginatedBoards != null)
  86. {
  87. @foreach (var board in paginatedBoards)
  88. {
  89. <div @onclick="() => SelectBoard(board.BoardId)" class="list-group-item d-flex justify-content-between align-items-center py-1 @(selectedBoardId == board.BoardId ? "active" : "")">
  90. <div style="cursor: pointer;">
  91. <div><strong>主板 @board.BoardId</strong></div>
  92. </div>
  93. <div>
  94. <button class="btn btn-sm btn-info me-1 p-1" @onclick="() => ShowEditBoardModal(board)">
  95. <i class="fas fa-edit"></i>
  96. </button>
  97. <button class="btn btn-sm btn-danger p-1" @onclick="() => DeleteBoard(board.BoardId)">
  98. <i class="fas fa-trash"></i>
  99. </button>
  100. </div>
  101. </div>
  102. }
  103. }
  104. </div>
  105. <!-- 主板分页控件 -->
  106. @if (filteredBoards != null && filteredBoards.Count > pageSize)
  107. {
  108. <nav aria-label="主板分页" class="position-absolute" style="bottom: 50px; left: 0; right: 0;">
  109. <ul class="pagination pagination-sm justify-content-center mt-2 mb-0">
  110. <li class="page-item @(currentPage_Board == 1 ? "disabled" : "")">
  111. <a class="page-link" @onclick="() => ChangePage_Board(currentPage_Board - 1)" tabindex="-1">上一页</a>
  112. </li>
  113. @for (int i = 1; i <= totalPages_Board; i++)
  114. {
  115. var item = i;
  116. <li class="page-item @(currentPage_Board == i ? "active" : "")">
  117. <a class="page-link" @onclick="() => ChangePage_Board(item)">@item</a>
  118. </li>
  119. }
  120. <li class="page-item @(currentPage_Board == totalPages_Board ? "disabled" : "")">
  121. <a class="page-link" @onclick="() => ChangePage_Board(currentPage_Board + 1)">下一页</a>
  122. </li>
  123. </ul>
  124. </nav>
  125. }
  126. </div>
  127. <!-- 油枪列 -->
  128. <div class="col-md-6 position-relative" style="height: calc(100vh - 100px);">
  129. <div class="d-flex justify-content-between align-items-center mb-3">
  130. <h5>油枪列表</h5>
  131. <button class="btn btn-sm btn-primary" @onclick="ShowCreateNozzleModal" disabled="@(selectedBoardId == 0)">
  132. <i class="fas fa-plus"></i>
  133. </button>
  134. </div>
  135. <!-- 油枪列表 -->
  136. <div class="list-group flex-grow-1" style="margin-bottom: 50px;">
  137. @if (paginatedNozzles != null)
  138. {
  139. @foreach (var nozzle in paginatedNozzles)
  140. {
  141. <div class="list-group-item d-flex justify-content-between align-items-center py-1">
  142. <div>
  143. <div><strong>油枪 @nozzle.NozzleId</strong></div>
  144. <small>节点: @nozzle.node | 产品: @nozzle.product | 状态: @(nozzle.disable ? "禁用" : "启用") | MN码: @nozzle.mncode</small>
  145. </div>
  146. <div>
  147. <button class="btn btn-sm btn-info me-1 p-1" @onclick="() => ShowEditNozzleModal(nozzle)">
  148. <i class="fas fa-edit"></i>
  149. </button>
  150. <button class="btn btn-sm btn-danger p-1" @onclick="() => DeleteNozzle(nozzle.NozzleId)">
  151. <i class="fas fa-trash"></i>
  152. </button>
  153. </div>
  154. </div>
  155. }
  156. }
  157. </div>
  158. <!-- 油枪分页控件 -->
  159. @if (filteredNozzles != null && filteredNozzles.Count > pageSize)
  160. {
  161. <nav aria-label="油枪分页" class="position-absolute" style="bottom: 50px; left: 0; right: 0;">
  162. <ul class="pagination pagination-sm justify-content-center mt-2 mb-0">
  163. <li class="page-item @(currentPage_Nozzle == 1 ? "disabled" : "")">
  164. <a class="page-link" @onclick="() => ChangePage_Nozzle(currentPage_Nozzle - 1)" tabindex="-1">上一页</a>
  165. </li>
  166. @for (int i = 1; i <= totalPages_Nozzle; i++)
  167. {
  168. var item = i;
  169. <li class="page-item @(currentPage_Nozzle == i ? "active" : "")">
  170. <a class="page-link" @onclick="() => ChangePage_Nozzle(item)">@item</a>
  171. </li>
  172. }
  173. <li class="page-item @(currentPage_Nozzle == totalPages_Nozzle ? "disabled" : "")">
  174. <a class="page-link" @onclick="() => ChangePage_Nozzle(currentPage_Nozzle + 1)">下一页</a>
  175. </li>
  176. </ul>
  177. </nav>
  178. }
  179. </div>
  180. </div>
  181. </div>
  182. <!-- 油机模态框 -->
  183. <div class="modal @(showEngineModal ? "show" : "")" tabindex="-1" style="display: @(showEngineModal ? "block" : "none"); background-color: rgba(0,0,0,0.5);">
  184. <div class="modal-dialog">
  185. <div class="modal-content">
  186. <div class="modal-header">
  187. <h5 class="modal-title">@engineModalTitle</h5>
  188. <button type="button" class="btn-close" @onclick="CloseEngineModal"></button>
  189. </div>
  190. <div class="modal-body">
  191. <div class="mb-3">
  192. <label class="form-label">油机ID</label>
  193. <div class="input-group">
  194. <input class="form-control" @bind="currentEngine.EngineId" disabled="@isEngineEditMode" />
  195. <button class="btn btn-outline-secondary" type="button" @onclick="ShowEngineIdSelector" disabled="@isEngineEditMode">
  196. <i class="fas fa-list"></i> 选择
  197. </button>
  198. </div>
  199. </div>
  200. <div class="mb-3">
  201. <label class="form-label">工厂ID</label>
  202. <input class="form-control" @bind="currentEngine.factory_id" />
  203. </div>
  204. <div class="mb-3">
  205. <label class="form-label">工厂ID 2</label>
  206. <input class="form-control" @bind="currentEngine.factory_id_2" />
  207. </div>
  208. </div>
  209. <div class="modal-footer">
  210. <button type="button" class="btn btn-secondary" @onclick="CloseEngineModal">取消</button>
  211. <button type="button" class="btn btn-primary" @onclick="SaveEngine">保存</button>
  212. </div>
  213. </div>
  214. </div>
  215. </div>
  216. <!-- 主板模态框 -->
  217. <div class="modal @(showBoardModal ? "show" : "")" tabindex="-1" style="display: @(showBoardModal ? "block" : "none"); background-color: rgba(0,0,0,0.5);">
  218. <div class="modal-dialog">
  219. <div class="modal-content">
  220. <div class="modal-header">
  221. <h5 class="modal-title">@boardModalTitle</h5>
  222. <button type="button" class="btn-close" @onclick="CloseBoardModal"></button>
  223. </div>
  224. <div class="modal-body">
  225. <div class="mb-3">
  226. <label class="form-label">所属油机ID</label>
  227. <select class="form-select" @bind="currentBoard.EngineId" disabled="@isBoardEditMode">
  228. <option value="0">请选择油机</option>
  229. @if (engines != null)
  230. {
  231. @foreach (var engine in engines)
  232. {
  233. <option value="@engine.EngineId">@engine.EngineId</option>
  234. }
  235. }
  236. </select>
  237. </div>
  238. <div class="mb-3">
  239. <label class="form-label">主板ID</label>
  240. <div class="input-group">
  241. <input class="form-control" @bind="currentBoard.BoardId" disabled="@isBoardEditMode" />
  242. <button class="btn btn-outline-secondary" type="button" @onclick="ShowBoardIdSelector" disabled="@isBoardEditMode">
  243. <i class="fas fa-list"></i> 选择
  244. </button>
  245. </div>
  246. </div>
  247. <div class="mb-3">
  248. <label class="form-label">IP地址</label>
  249. <input class="form-control" @bind="currentBoard.ip" />
  250. </div>
  251. </div>
  252. <div class="modal-footer">
  253. <button type="button" class="btn btn-secondary" @onclick="CloseBoardModal">取消</button>
  254. <button type="button" class="btn btn-primary" @onclick="SaveBoard">保存</button>
  255. </div>
  256. </div>
  257. </div>
  258. </div>
  259. <!-- 油枪模态框 -->
  260. <div class="modal @(showNozzleModal ? "show" : "")" tabindex="-1" style="display: @(showNozzleModal ? "block" : "none"); background-color: rgba(0,0,0,0.5);">
  261. <div class="modal-dialog">
  262. <div class="modal-content">
  263. <div class="modal-header">
  264. <h5 class="modal-title">@nozzleModalTitle</h5>
  265. <button type="button" class="btn-close" @onclick="CloseNozzleModal"></button>
  266. </div>
  267. <div class="modal-body">
  268. <div class="mb-3">
  269. <label class="form-label">油枪ID</label>
  270. <div class="input-group">
  271. <input type="number" class="form-control" @bind="currentNozzle.NozzleId" disabled="@isNozzleEditMode" />
  272. <button class="btn btn-outline-secondary" type="button" @onclick="ShowNozzleIdSelector" disabled="@isNozzleEditMode">
  273. <i class="fas fa-list"></i> 选择
  274. </button>
  275. </div>
  276. </div>
  277. <div class="mb-3">
  278. <label class="form-label">所属主板ID</label>
  279. <select class="form-select" @bind="currentNozzle.BoardId" disabled="@isNozzleEditMode">
  280. <option value="0">请选择主板</option>
  281. @if (boards != null)
  282. {
  283. @foreach (var board in boards)
  284. {
  285. <option value="@board.BoardId">@board.BoardId (油机:@board.EngineId)</option>
  286. }
  287. }
  288. </select>
  289. </div>
  290. <div class="mb-3">
  291. <label class="form-label">节点</label>
  292. <input type="number" class="form-control" @bind="currentNozzle.node" />
  293. </div>
  294. <div class="mb-3">
  295. <label class="form-label">产品</label>
  296. <input type="number" class="form-control" @bind="currentNozzle.product" />
  297. </div>
  298. <div class="mb-3 form-check">
  299. <input type="checkbox" class="form-check-input" @bind="currentNozzle.disable" />
  300. <label class="form-check-label">禁用</label>
  301. </div>
  302. <div class="mb-3">
  303. <label class="form-label">MN码</label>
  304. <input class="form-control" @bind="currentNozzle.mncode" />
  305. </div>
  306. </div>
  307. <div class="modal-footer">
  308. <button type="button" class="btn btn-secondary" @onclick="CloseNozzleModal">取消</button>
  309. <button type="button" class="btn btn-primary" @onclick="SaveNozzle">保存</button>
  310. </div>
  311. </div>
  312. </div>
  313. </div>
  314. @code {
  315. // 数据列表
  316. private List<TEngine> engines = new();
  317. private List<TBoard> allBoards = new();
  318. private List<TBoard> filteredBoards = new();
  319. private List<TNozzle> allNozzles = new();
  320. private List<TNozzle> filteredNozzles = new();
  321. private List<TBoard> boards = new(); // 用于下拉选择
  322. // 分页相关
  323. private const int pageSize = 8; // 每页显示条数
  324. private int currentPage_Engine = 1;
  325. private int totalPages_Engine => engines == null ? 0 : (int)Math.Ceiling((double)engines.Count / pageSize);
  326. private List<TEngine> paginatedEngines => engines?.Skip((currentPage_Engine - 1) * pageSize).Take(pageSize).ToList() ?? new List<TEngine>();
  327. private int currentPage_Board = 1;
  328. private int totalPages_Board => filteredBoards == null ? 0 : (int)Math.Ceiling((double)filteredBoards.Count / pageSize);
  329. private List<TBoard> paginatedBoards => filteredBoards?.Skip((currentPage_Board - 1) * pageSize).Take(pageSize).ToList() ?? new List<TBoard>();
  330. private int currentPage_Nozzle = 1;
  331. private int totalPages_Nozzle => filteredNozzles == null ? 0 : (int)Math.Ceiling((double)filteredNozzles.Count / pageSize);
  332. private List<TNozzle> paginatedNozzles => filteredNozzles?.Skip((currentPage_Nozzle - 1) * pageSize).Take(pageSize).ToList() ?? new List<TNozzle>();
  333. // 当前选中项
  334. private int selectedEngineId = 0;
  335. private int selectedBoardId = 0;
  336. // 油机相关
  337. private TEngine currentEngine = new();
  338. private string engineModalTitle = "";
  339. private bool isEngineEditMode = false;
  340. private bool showEngineModal = false;
  341. // 主板相关
  342. private TBoard currentBoard = new();
  343. private string boardModalTitle = "";
  344. private bool isBoardEditMode = false;
  345. private bool showBoardModal = false;
  346. // 油枪相关
  347. private TNozzle currentNozzle = new();
  348. private string nozzleModalTitle = "";
  349. private bool isNozzleEditMode = false;
  350. private bool showNozzleModal = false;
  351. protected override async Task OnInitializedAsync()
  352. {
  353. await LoadAllData();
  354. }
  355. private async Task LoadAllData()
  356. {
  357. try
  358. {
  359. // 加载所有数据
  360. engines = await nozzleService.GetEnginesWithDetailsAsync();
  361. allBoards = await nozzleService.GetBoardsAsync();
  362. allNozzles = await nozzleService.GetNozzlesAsync();
  363. boards = new List<TBoard>(allBoards); // 用于下拉选择
  364. // 默认显示所有数据
  365. //filteredBoards = new List<TBoard>(allBoards);
  366. //filteredNozzles = new List<TNozzle>(allNozzles);
  367. // 重置分页
  368. currentPage_Engine = 1;
  369. currentPage_Board = 1;
  370. currentPage_Nozzle = 1;
  371. StateHasChanged();
  372. }
  373. catch (Exception ex)
  374. {
  375. await JSRuntime.InvokeVoidAsync("alert", $"加载数据失败: {ex.Message}");
  376. }
  377. }
  378. // 分页切换方法
  379. private void ChangePage_Engine(int page)
  380. {
  381. if (page >= 1 && page <= totalPages_Engine)
  382. {
  383. currentPage_Engine = page;
  384. StateHasChanged();
  385. }
  386. }
  387. private void ChangePage_Board(int page)
  388. {
  389. if (page >= 1 && page <= totalPages_Board)
  390. {
  391. currentPage_Board = page;
  392. StateHasChanged();
  393. }
  394. }
  395. private void ChangePage_Nozzle(int page)
  396. {
  397. if (page >= 1 && page <= totalPages_Nozzle)
  398. {
  399. currentPage_Nozzle = page;
  400. StateHasChanged();
  401. }
  402. }
  403. // 油机选择
  404. private void SelectEngine(int engineId)
  405. {
  406. selectedEngineId = engineId;
  407. selectedBoardId = 0; // 重置主板选择
  408. if (engineId == 0)
  409. {
  410. // 显示所有主板和油枪
  411. //filteredBoards = new List<TBoard>(allBoards);
  412. //filteredNozzles = new List<TNozzle>(allNozzles);
  413. }
  414. else
  415. {
  416. // 只显示选定油机的主板
  417. filteredBoards = allBoards.Where(b => b.EngineId == engineId).ToList();
  418. // 显示这些主板下的所有油枪
  419. var boardIds = filteredBoards.Select(b => b.BoardId).ToList();
  420. filteredNozzles = allNozzles.Where(n => boardIds.Contains(n.BoardId)).ToList();
  421. }
  422. // 重置分页
  423. currentPage_Board = 1;
  424. currentPage_Nozzle = 1;
  425. StateHasChanged();
  426. }
  427. // 主板选择
  428. private void SelectBoard(int boardId)
  429. {
  430. selectedBoardId = boardId;
  431. if (boardId == 0)
  432. {
  433. // 如果选择了"显示所有主板",则显示当前筛选条件下的所有油枪
  434. if (selectedEngineId == 0)
  435. {
  436. filteredNozzles = new List<TNozzle>(allNozzles);
  437. }
  438. else
  439. {
  440. var boardIds = filteredBoards.Select(b => b.BoardId).ToList();
  441. filteredNozzles = allNozzles.Where(n => boardIds.Contains(n.BoardId)).ToList();
  442. }
  443. }
  444. else
  445. {
  446. // 只显示选定主板的油枪
  447. filteredNozzles = allNozzles.Where(n => n.BoardId == boardId).ToList();
  448. }
  449. // 重置油枪分页
  450. currentPage_Nozzle = 1;
  451. StateHasChanged();
  452. }
  453. // ===== 油机操作 =====
  454. private void ShowCreateEngineModal()
  455. {
  456. currentEngine = new TEngine();
  457. engineModalTitle = "添加油机";
  458. isEngineEditMode = false;
  459. showEngineModal = true;
  460. StateHasChanged();
  461. }
  462. private void ShowEditEngineModal(TEngine engine)
  463. {
  464. currentEngine = new TEngine
  465. {
  466. EngineId = engine.EngineId,
  467. factory_id = engine.factory_id,
  468. factory_id_2 = engine.factory_id_2
  469. };
  470. engineModalTitle = "编辑油机";
  471. isEngineEditMode = true;
  472. showEngineModal = true;
  473. StateHasChanged();
  474. }
  475. private void CloseEngineModal()
  476. {
  477. showEngineModal = false;
  478. StateHasChanged();
  479. }
  480. private async Task SaveEngine()
  481. {
  482. try
  483. {
  484. if (isEngineEditMode)
  485. {
  486. await nozzleService.UpdateEngineAsync(currentEngine);
  487. }
  488. else
  489. {
  490. await nozzleService.CreateEngineAsync(currentEngine);
  491. }
  492. CloseEngineModal();
  493. await LoadAllData();
  494. // 重新选择当前油机以刷新视图
  495. if (selectedEngineId > 0)
  496. {
  497. SelectEngine(selectedEngineId);
  498. }
  499. }
  500. catch (Exception ex)
  501. {
  502. await JSRuntime.InvokeVoidAsync("alert", $"操作失败: {ex.Message}");
  503. }
  504. }
  505. private async Task DeleteEngine(int id)
  506. {
  507. var confirmed = await JSRuntime.InvokeAsync<bool>("confirm", "确定要删除这个油机吗?这将同时删除其下属的所有主板和油枪!");
  508. if (confirmed)
  509. {
  510. try
  511. {
  512. await nozzleService.DeleteEngineAsync(id);
  513. await LoadAllData();
  514. // 如果删除的是当前选中的油机,重置选择
  515. if (selectedEngineId == id)
  516. {
  517. SelectEngine(0);
  518. }
  519. }
  520. catch (Exception ex)
  521. {
  522. await JSRuntime.InvokeVoidAsync("alert", $"删除失败: {ex.Message}");
  523. }
  524. }
  525. }
  526. // ===== 主板操作 =====
  527. private void ShowCreateBoardModal()
  528. {
  529. if (selectedEngineId == 0)
  530. {
  531. JSRuntime.InvokeVoidAsync("alert", "请先选择一个油机");
  532. return;
  533. }
  534. currentBoard = new TBoard { EngineId = selectedEngineId };
  535. boardModalTitle = "添加主板";
  536. isBoardEditMode = false;
  537. showBoardModal = true;
  538. StateHasChanged();
  539. }
  540. private void ShowEditBoardModal(TBoard board)
  541. {
  542. currentBoard = new TBoard
  543. {
  544. BoardId = board.BoardId,
  545. EngineId = board.EngineId,
  546. ip = board.ip
  547. };
  548. boardModalTitle = "编辑主板";
  549. isBoardEditMode = true;
  550. showBoardModal = true;
  551. StateHasChanged();
  552. }
  553. private void CloseBoardModal()
  554. {
  555. showBoardModal = false;
  556. StateHasChanged();
  557. }
  558. private async Task SaveBoard()
  559. {
  560. if (currentBoard.EngineId <= 0)
  561. {
  562. await JSRuntime.InvokeVoidAsync("alert", "请选择有效的油机ID");
  563. return;
  564. }
  565. try
  566. {
  567. if (isBoardEditMode)
  568. {
  569. await nozzleService.UpdateBoardAsync(currentBoard);
  570. }
  571. else
  572. {
  573. await nozzleService.CreateBoardAsync(currentBoard);
  574. }
  575. CloseBoardModal();
  576. await LoadAllData();
  577. // 重新选择当前筛选条件
  578. if (selectedEngineId > 0)
  579. {
  580. SelectEngine(selectedEngineId);
  581. }
  582. }
  583. catch (Exception ex)
  584. {
  585. await JSRuntime.InvokeVoidAsync("alert", $"操作失败: {ex.Message}");
  586. }
  587. }
  588. private async Task DeleteBoard(int id)
  589. {
  590. var confirmed = await JSRuntime.InvokeAsync<bool>("confirm", "确定要删除这个主板吗?这将同时删除其下属的所有油枪!");
  591. if (confirmed)
  592. {
  593. try
  594. {
  595. await nozzleService.DeleteBoardAsync(id);
  596. await LoadAllData();
  597. // 如果删除的是当前选中的主板,重置选择
  598. if (selectedBoardId == id)
  599. {
  600. SelectBoard(0);
  601. }
  602. }
  603. catch (Exception ex)
  604. {
  605. await JSRuntime.InvokeVoidAsync("alert", $"删除失败: {ex.Message}");
  606. }
  607. }
  608. }
  609. // ===== 油枪操作 =====
  610. private void ShowCreateNozzleModal()
  611. {
  612. if (selectedBoardId == 0)
  613. {
  614. JSRuntime.InvokeVoidAsync("alert", "请先选择一个主板");
  615. return;
  616. }
  617. currentNozzle = new TNozzle { BoardId = selectedBoardId };
  618. nozzleModalTitle = "添加油枪";
  619. isNozzleEditMode = false;
  620. showNozzleModal = true;
  621. StateHasChanged();
  622. }
  623. private void ShowEditNozzleModal(TNozzle nozzle)
  624. {
  625. currentNozzle = new TNozzle
  626. {
  627. NozzleId = nozzle.NozzleId,
  628. BoardId = nozzle.BoardId,
  629. node = nozzle.node,
  630. product = nozzle.product,
  631. disable = nozzle.disable,
  632. mncode = nozzle.mncode
  633. };
  634. nozzleModalTitle = "编辑油枪";
  635. isNozzleEditMode = true;
  636. showNozzleModal = true;
  637. StateHasChanged();
  638. }
  639. private void CloseNozzleModal()
  640. {
  641. showNozzleModal = false;
  642. StateHasChanged();
  643. }
  644. private async Task SaveNozzle()
  645. {
  646. if (currentNozzle.BoardId <= 0)
  647. {
  648. await JSRuntime.InvokeVoidAsync("alert", "请选择有效的主板ID");
  649. return;
  650. }
  651. try
  652. {
  653. if (isNozzleEditMode)
  654. {
  655. await nozzleService.UpdateNozzleAsync(currentNozzle);
  656. }
  657. else
  658. {
  659. await nozzleService.CreateNozzleAsync(currentNozzle);
  660. }
  661. CloseNozzleModal();
  662. await LoadAllData();
  663. // 重新应用当前筛选
  664. if (selectedBoardId > 0)
  665. {
  666. SelectBoard(selectedBoardId);
  667. }
  668. else if (selectedEngineId > 0)
  669. {
  670. SelectEngine(selectedEngineId);
  671. }
  672. }
  673. catch (Exception ex)
  674. {
  675. await JSRuntime.InvokeVoidAsync("alert", $"操作失败: {ex.Message}");
  676. }
  677. }
  678. private async Task DeleteNozzle(int id)
  679. {
  680. var confirmed = await JSRuntime.InvokeAsync<bool>("confirm", "确定要删除这个油枪吗?");
  681. if (confirmed)
  682. {
  683. try
  684. {
  685. await nozzleService.DeleteNozzleAsync(id);
  686. await LoadAllData();
  687. // 重新应用当前筛选
  688. if (selectedBoardId > 0)
  689. {
  690. SelectBoard(selectedBoardId);
  691. }
  692. else if (selectedEngineId > 0)
  693. {
  694. SelectEngine(selectedEngineId);
  695. }
  696. }
  697. catch (Exception ex)
  698. {
  699. await JSRuntime.InvokeVoidAsync("alert", $"删除失败: {ex.Message}");
  700. }
  701. }
  702. }
  703. // ID选择器相关状态
  704. private bool showEngineIdSelector = false;
  705. private bool showBoardIdSelector = false;
  706. private bool showNozzleIdSelector = false;
  707. // 显示ID选择器
  708. private void ShowEngineIdSelector()
  709. {
  710. showEngineIdSelector = true;
  711. StateHasChanged();
  712. }
  713. private void ShowBoardIdSelector()
  714. {
  715. showBoardIdSelector = true;
  716. StateHasChanged();
  717. }
  718. private void ShowNozzleIdSelector()
  719. {
  720. showNozzleIdSelector = true;
  721. StateHasChanged();
  722. }
  723. // ID选择回调
  724. private void OnEngineIdSelected(int id)
  725. {
  726. currentEngine.EngineId = id;
  727. showEngineIdSelector = false;
  728. StateHasChanged();
  729. }
  730. private void OnBoardIdSelected(int id)
  731. {
  732. currentBoard.BoardId = id;
  733. showBoardIdSelector = false;
  734. StateHasChanged();
  735. }
  736. private void OnNozzleIdSelected(int id)
  737. {
  738. currentNozzle.NozzleId = id;
  739. showNozzleIdSelector = false;
  740. StateHasChanged();
  741. }
  742. // 取消选择
  743. private void CancelEngineIdSelection()
  744. {
  745. showEngineIdSelector = false;
  746. StateHasChanged();
  747. }
  748. private void CancelBoardIdSelection()
  749. {
  750. showBoardIdSelector = false;
  751. StateHasChanged();
  752. }
  753. private void CancelNozzleIdSelection()
  754. {
  755. showNozzleIdSelector = false;
  756. StateHasChanged();
  757. }
  758. // 获取已使用的ID列表
  759. private List<int> GetUsedEngineIds()
  760. {
  761. return engines?.Select(e => e.EngineId).ToList() ?? new List<int>();
  762. }
  763. private List<int> GetUsedBoardIds()
  764. {
  765. return allBoards?.Select(b => b.BoardId).ToList() ?? new List<int>();
  766. }
  767. private List<int> GetUsedNozzleIds()
  768. {
  769. return allNozzles?.Select(n => n.NozzleId).ToList() ?? new List<int>();
  770. }
  771. }
  772. <!-- ID选择器组件 -->
  773. @if (showEngineIdSelector)
  774. {
  775. <EngineIdSelector usedEngineIds="GetUsedEngineIds()"
  776. OnSelected="OnEngineIdSelected"
  777. OnCancelled="CancelEngineIdSelection" />
  778. }
  779. @if (showBoardIdSelector)
  780. {
  781. <BoardIdSelector usedBoardIds="GetUsedBoardIds()"
  782. OnSelected="OnBoardIdSelected"
  783. OnCancelled="CancelBoardIdSelection" />
  784. }
  785. @if (showNozzleIdSelector)
  786. {
  787. <NozzleIdSelector usedNozzleIds="GetUsedNozzleIds()"
  788. OnSelected="OnNozzleIdSelected"
  789. OnCancelled="CancelNozzleIdSelection" />
  790. }