MesController.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. using LocalhostMES.Core;
  2. using LocalhostMES.DataBase;
  3. using LocalhostMES.Models;
  4. using Newtonsoft.Json;
  5. using Prism.Ioc;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Web.Http;
  13. using System.Web.UI.WebControls.WebParts;
  14. namespace LocalhostMES.Controller
  15. {
  16. [RoutePrefix("api/mes")]
  17. public class MesController : ApiController
  18. {
  19. private static readonly Random _random = new Random();
  20. private static int _snCounter = 1;
  21. private Management management;
  22. public MesController()
  23. {
  24. management = Management.GetManagement();
  25. }
  26. #region 2.1 厂级MES下发工单信息
  27. [HttpPost]
  28. [Route("receiveWorkOrder")]
  29. public IHttpActionResult ReceiveWorkOrder([FromBody] WorkOrderRequest request)
  30. {
  31. try
  32. {
  33. LogHelper.WriteLogInfo("厂级MES下发工单信息");
  34. // 验证必填字段
  35. if (string.IsNullOrEmpty(request.WorkOrderNo) ||
  36. string.IsNullOrEmpty(request.MaterialCode) ||
  37. string.IsNullOrEmpty(request.MaterialName) ||
  38. string.IsNullOrEmpty(request.LineCode))
  39. {
  40. LogHelper.WriteLogInfo("必填字段不能为空");
  41. return BadRequest("必填字段不能为空");
  42. }
  43. // 工单状态验证
  44. if (!IsValidStatus(request.Status))
  45. {
  46. LogHelper.WriteLogInfo("无效的工单状态");
  47. return BadRequest($"无效的工单状态: {request.Status}");
  48. }
  49. // 创建或更新工单信息
  50. var workOrder = new WorkOrderInfo
  51. {
  52. WorkOrderNo = request.WorkOrderNo,
  53. MaterialCode = request.MaterialCode,
  54. OrderNo = request.OrderNo,
  55. MaterialName = request.MaterialName,
  56. PlannedQuantity = int.TryParse(request.WorkOrderNum, out var qty) ? qty : 0,
  57. CompletedQuantity = 0,
  58. Status = request.Status,
  59. LineCode = request.LineCode,
  60. CreateTime = DateTime.Now,
  61. StartTime = DateTime.Now.AddSeconds(2),
  62. EndTime = DateTime.Now.AddSeconds(5)
  63. };
  64. if (DatabaseHelper.InsertWorkOrderInfo(workOrder))
  65. {
  66. var response = new ApiResponse<bool>
  67. {
  68. code = "200",
  69. success = true,
  70. msg = "工单接收成功",
  71. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  72. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  73. data = true
  74. };
  75. LogHelper.WriteLogInfo("工单接收成功");
  76. return Ok(response);
  77. }
  78. else
  79. {
  80. var errorResponse = new ErrorResponse
  81. {
  82. code = "55000",
  83. success = false,
  84. msg = $"工单接收失败:数据库插入异常",
  85. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  86. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  87. };
  88. LogHelper.WriteLogInfo("数据库插入异常");
  89. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  90. }
  91. }
  92. catch (Exception ex)
  93. {
  94. var errorResponse = new ErrorResponse
  95. {
  96. code = "55000",
  97. success = false,
  98. msg = $"工单接收失败: {ex.Message}",
  99. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  100. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  101. };
  102. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  103. }
  104. }
  105. [HttpGet]
  106. [Route("getWorkOrders")]
  107. public IHttpActionResult GetWorkOrders()
  108. {
  109. try
  110. {
  111. LogHelper.WriteLogInfo("接口getWorkOrders收到消息");
  112. var workOrders = DatabaseHelper.SelectWorkOrderInfo(null, management.IsLocalhostMode);
  113. var response = new ApiResponse<List<WorkOrderInfo>>
  114. {
  115. code = "200",
  116. success = true,
  117. msg = "获取成功",
  118. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  119. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  120. data = workOrders
  121. };
  122. return Ok(response);
  123. }
  124. catch (Exception ex)
  125. {
  126. var errorResponse = new ErrorResponse
  127. {
  128. code = "55000",
  129. success = false,
  130. msg = $"获取工单失败: {ex.Message}",
  131. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  132. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  133. };
  134. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  135. }
  136. }
  137. #endregion
  138. #region 2.2 SN打印请求
  139. [HttpPost]
  140. [Route("requestSnPrint")]
  141. public async Task<IHttpActionResult> RequestSnPrint([FromBody] SnPrintRequest request)
  142. {
  143. try
  144. {
  145. // 验证请求头
  146. if (!ValidateHeaders())
  147. {
  148. return Unauthorized();
  149. }
  150. // 验证必填字段
  151. if (string.IsNullOrEmpty(request.workOrderNo) || request.count <= 0)
  152. {
  153. return BadRequest("工单号和数量为必填项且数量必须大于0");
  154. }
  155. var workOrder = DatabaseHelper.SelectWorkOrderInfo(request.workOrderNo);
  156. // 验证工单是否存在
  157. if (workOrder.Count == 0)
  158. {
  159. return BadRequest($"工单 {request.workOrderNo} 不存在");
  160. }
  161. // 验证打印类型
  162. if (request.printType < 1 || request.printType > 4)
  163. {
  164. return BadRequest($"无效的打印类型: {request.printType}");
  165. }
  166. LogHelper.WriteLogInfo("请求参数:");
  167. LogHelper.WriteLogInfo(JsonConvert.SerializeObject(request, Formatting.Indented));
  168. if (management.IsLocalhostMode)
  169. {
  170. var Manualsninfo = DatabaseHelper.SelectSnInfo(request.workOrderNo);
  171. DatabaseHelper.InsertSnInfo(new SnInfo()
  172. {
  173. Sn = "000001" +DateCodeConverter.GetYearCode(DateTime.Now.Year) +
  174. DateCodeConverter.GetMonthCode(DateTime.Now.Month) +
  175. DateCodeConverter.GetDayCode(DateTime.Now.Day) +
  176. "00000" + Manualsninfo.Count,
  177. IsUsed = false,
  178. WorkOrderNo= request.workOrderNo,
  179. GenerateTime=DateTime.Now,
  180. PrintType="1",
  181. });
  182. }
  183. var sninfo = DatabaseHelper.SelectSnInfo(request.workOrderNo, true, false);
  184. if (sninfo.Count == 0)
  185. {
  186. ApiResponse<SnPrintResponseData> mesres = await management.ApiClient.RequestSnPrintAsync(request);
  187. if (mesres.success && mesres.data!=null&& mesres.data.Sn.Count != 0)
  188. {
  189. for (int i = 0; i < mesres.data.Sn.Count; i++)
  190. {
  191. if (!DatabaseHelper.InsertSnInfo(new SnInfo()
  192. {
  193. WorkOrderNo = mesres.data.WorkOrderNo,
  194. Sn = mesres.data.Sn[i].Sn,
  195. GenerateTime = DateTime.Now,
  196. PrintType = "1",
  197. IsUsed = false,
  198. }))
  199. {
  200. mesres.msg = "插入SN到数据库出错";
  201. mesres.success = false;
  202. return Content(System.Net.HttpStatusCode.InternalServerError, mesres);
  203. }
  204. }
  205. return Ok(mesres);
  206. }
  207. return Content(System.Net.HttpStatusCode.InternalServerError, mesres);
  208. }
  209. // 生成SN列表
  210. var snList = new List<SnItem>();
  211. if (sninfo.Count != 0)
  212. {
  213. snList.Add(new SnItem { Sn = sninfo[0].Sn });
  214. var responseData = new SnPrintResponseData
  215. {
  216. Sn = snList,
  217. OrderNo = request.orderNo ?? "",
  218. WorkOrderNo = request.workOrderNo,
  219. Line = request.line ?? "",
  220. VehicleCode = workOrder[0].MaterialCode,
  221. MaterialDesc = workOrder[0].MaterialName
  222. };
  223. var response = new ApiResponse<SnPrintResponseData>
  224. {
  225. code = "200",
  226. success = true,
  227. msg = "SN生成成功",
  228. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  229. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  230. data = responseData
  231. };
  232. return Ok(response);
  233. }
  234. var errorResponse = new ErrorResponse
  235. {
  236. code = "55000",
  237. success = false,
  238. msg = $"SN获取失败",
  239. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  240. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  241. };
  242. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  243. }
  244. catch (Exception ex)
  245. {
  246. var errorResponse = new ErrorResponse
  247. {
  248. code = "55000",
  249. success = false,
  250. msg = $"SN生成失败: {ex.Message}",
  251. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  252. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  253. };
  254. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  255. }
  256. }
  257. [HttpGet]
  258. [Route("getSns/{workOrderNo}")]
  259. public IHttpActionResult GetSns(string workOrderNo)
  260. {
  261. try
  262. {
  263. var sninfo = DatabaseHelper.SelectSnInfo(workOrderNo, true, false);
  264. if (sninfo.Count != 0)
  265. {
  266. var response = new ApiResponse<List<SnInfo>>
  267. {
  268. code = "200",
  269. success = true,
  270. msg = "获取成功",
  271. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  272. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  273. data = sninfo
  274. };
  275. return Ok(response);
  276. }
  277. var errorResponse = new ErrorResponse
  278. {
  279. code = "55001",
  280. success = false,
  281. msg = $"工单 {workOrderNo} 没有SN记录",
  282. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  283. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  284. };
  285. return Content(System.Net.HttpStatusCode.NotFound, errorResponse);
  286. }
  287. catch (Exception ex)
  288. {
  289. var errorResponse = new ErrorResponse
  290. {
  291. code = "55000",
  292. success = false,
  293. msg = $"获取SN失败: {ex.Message}",
  294. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  295. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  296. };
  297. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  298. }
  299. }
  300. #endregion
  301. #region 2.3 接收SN和关键件
  302. [HttpPost]
  303. [Route("receiveSnComponent")]
  304. public async Task<IHttpActionResult> ReceiveSnComponent([FromBody] SnKeyComponentRequest request)
  305. {
  306. try
  307. {
  308. LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件");
  309. if (management.IsLocalhostMode)
  310. {
  311. return Ok(new ApiResponse<bool?>() { data = true });
  312. }
  313. // 验证请求头
  314. if (!ValidateHeaders())
  315. {
  316. return Unauthorized();
  317. }
  318. // 验证必填字段
  319. if (string.IsNullOrEmpty(request.plant) ||
  320. string.IsNullOrEmpty(request.stationCode) ||
  321. string.IsNullOrEmpty(request.positionCode) ||
  322. string.IsNullOrEmpty(request.sn) ||
  323. string.IsNullOrEmpty(request.scanTime))
  324. {
  325. return BadRequest("必填字段不能为空");
  326. }
  327. // 处理关键件绑定
  328. if (request.part != null && request.part.Count > 0)
  329. {
  330. foreach (var part in request.part)
  331. {
  332. if (string.IsNullOrEmpty(part.partNum))
  333. {
  334. return BadRequest("关键件条码不能为空");
  335. }
  336. var bindRecord = new BindRecord
  337. {
  338. Sn = request.sn,
  339. PartNum = part.partNum,
  340. StationCode = request.stationCode,
  341. BindTime = DateTime.TryParse(request.scanTime, out var scanTime) ? scanTime : DateTime.Now,
  342. Employee = request.employee ?? "",
  343. ScanType = request.scanTpye
  344. };
  345. DatabaseHelper.InsertBindRecord(bindRecord);
  346. if (management.IsLocalhostMode)
  347. {
  348. //if (DatabaseHelper.GetProductProductionRecords(request.sn) == 0)
  349. //{
  350. var response = new ApiResponse<bool>
  351. {
  352. code = "200",
  353. success = true,
  354. msg = "已存在记录",
  355. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  356. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  357. data = true
  358. };
  359. return Ok(response);
  360. }
  361. }
  362. }
  363. else
  364. {
  365. var bindRecord = new BindRecord
  366. {
  367. Sn = request.sn,
  368. PartNum ="",
  369. StationCode = request.stationCode,
  370. BindTime = DateTime.TryParse(request.scanTime, out var scanTime) ? scanTime : DateTime.Now,
  371. Employee = request.employee ?? "",
  372. ScanType = request.scanTpye
  373. };
  374. DatabaseHelper.InsertBindRecord(bindRecord);
  375. }
  376. if (management.IsLocalhostMode)
  377. {
  378. LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件 成功");
  379. return Ok(new ApiResponse<bool?>() { data=true} );
  380. }
  381. var okresponse = await management.ApiClient.SendSnComponentAsync(request);
  382. if (okresponse.success && okresponse.code == "200")
  383. {
  384. LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件 成功");
  385. return Ok(okresponse);
  386. }
  387. else
  388. {
  389. LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件 失败\r\n"+ okresponse.ToString());
  390. okresponse.success = false;
  391. return Content(System.Net.HttpStatusCode.InternalServerError, okresponse);
  392. }
  393. }
  394. catch (Exception ex)
  395. {
  396. var errorResponse = new ErrorResponse
  397. {
  398. code = "55000",
  399. success = false,
  400. msg = $"SN和关键件接收失败: {ex.Message}",
  401. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  402. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  403. };
  404. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  405. }
  406. }
  407. [HttpGet]
  408. [Route("getBindRecords")]
  409. public IHttpActionResult GetBindRecords()
  410. {
  411. try
  412. {
  413. var records = DatabaseHelper.SelectBindRecord();
  414. var response = new ApiResponse<List<BindRecord>>
  415. {
  416. code = "200",
  417. success = true,
  418. msg = "获取成功",
  419. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  420. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  421. data = records
  422. };
  423. return Ok(response);
  424. }
  425. catch (Exception ex)
  426. {
  427. var errorResponse = new ErrorResponse
  428. {
  429. code = "55000",
  430. success = false,
  431. msg = $"获取绑定记录失败: {ex.Message}",
  432. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  433. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  434. };
  435. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  436. }
  437. }
  438. #endregion
  439. #region 2.4 接收工件加工参数
  440. [HttpPost]
  441. [Route("receiveProcessParameters")]
  442. public async Task<IHttpActionResult> ReceiveProcessParameters([FromBody] ProcessParameterRequest request)
  443. {
  444. try
  445. {
  446. LogHelper.WriteLogInfo($"收到请求:接收工件加工参数 ");
  447. // 验证请求头
  448. if (!ValidateHeaders())
  449. {
  450. return Unauthorized();
  451. }
  452. // 验证必填字段
  453. if (string.IsNullOrEmpty(request.plant) ||
  454. string.IsNullOrEmpty(request.station) ||
  455. string.IsNullOrEmpty(request.sn) ||
  456. string.IsNullOrEmpty(request.overallResult))
  457. {
  458. return BadRequest("必填字段不能为空");
  459. }
  460. // 验证总结果
  461. if (request.overallResult != "OK" && request.overallResult != "NG")
  462. {
  463. return BadRequest($"无效的总结果: {request.overallResult}");
  464. }
  465. // 保存加工记录
  466. var processRecord = new ProcessRecord
  467. {
  468. Sn = request.sn,
  469. Station = request.station,
  470. OverallResult = request.overallResult,
  471. ProcessTime = DateTime.Now,
  472. Equipment = request.equipment ?? ""
  473. };
  474. DatabaseHelper.InsertProcessRecord(processRecord);
  475. if (management.IsLocalhostMode)
  476. {
  477. var response = new ApiResponse<bool>
  478. {
  479. code = "200",
  480. success = true,
  481. msg = "加工参数接收成功",
  482. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  483. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  484. data = true
  485. };
  486. LogHelper.WriteLogInfo($"收到请求:接收工件加工参数 成功");
  487. return Ok(response);
  488. }
  489. var okresponse = await management.ApiClient.SendProcessParametersAsync(request);
  490. if (okresponse.success && okresponse.code == "200")
  491. {
  492. LogHelper.WriteLogInfo($"收到请求: 接收工件加工参数 成功");
  493. return Ok(okresponse);
  494. }
  495. else
  496. {
  497. LogHelper.WriteLogInfo($"收到请求: 接收工件加工参数 失败\r\n" + okresponse.ToString());
  498. okresponse.success = false;
  499. return Content(System.Net.HttpStatusCode.InternalServerError, okresponse);
  500. }
  501. }
  502. catch (Exception ex)
  503. {
  504. LogHelper.WriteLogInfo("出错");
  505. var errorResponse = new ErrorResponse
  506. {
  507. code = "55000",
  508. success = false,
  509. msg = $"加工参数接收失败: {ex.Message}",
  510. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  511. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  512. };
  513. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  514. }
  515. }
  516. [HttpGet]
  517. [Route("getProcessRecords")]
  518. public IHttpActionResult GetProcessRecords()
  519. {
  520. try
  521. {
  522. var records = DatabaseHelper.SelectProcessRecord();
  523. var response = new ApiResponse<List<ProcessRecord>>
  524. {
  525. code = "200",
  526. success = true,
  527. msg = "获取成功",
  528. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  529. traceId = Guid.NewGuid().ToString("N").Substring(0, 24),
  530. data = records
  531. };
  532. return Ok(response);
  533. }
  534. catch (Exception ex)
  535. {
  536. var errorResponse = new ErrorResponse
  537. {
  538. code = "55000",
  539. success = false,
  540. msg = $"获取加工记录失败: {ex.Message}",
  541. msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  542. traceId = Guid.NewGuid().ToString("N").Substring(0, 24)
  543. };
  544. return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse);
  545. }
  546. }
  547. #endregion
  548. #region 辅助方法
  549. private bool ValidateHeaders()
  550. {
  551. // 简单的token验证
  552. if (Request.Headers.TryGetValues("app-key", out var appKeyValues) &&
  553. Request.Headers.TryGetValues("token", out var tokenValues))
  554. {
  555. var appKey = appKeyValues.FirstOrDefault();
  556. var token = tokenValues.FirstOrDefault();
  557. // 这里使用简单的验证
  558. return appKey == "test-app-key" && token == "test-token-123";
  559. }
  560. return false;
  561. }
  562. private bool IsValidStatus(string status)
  563. {
  564. var validStatuses = new[] { "0", "1", "2", "3", "4", "5", "6", "7" };
  565. return validStatuses.Contains(status);
  566. }
  567. private string GenerateSn(WorkOrderInfo workOrder, int printType)
  568. {
  569. var prefix = GetPrintTypePrefix(printType);
  570. var timestamp = DateTime.Now.ToString("yyMMddHHmm");
  571. var randomStr = Guid.NewGuid().ToString("N").Substring(0, 6).ToUpper();
  572. var counter = Interlocked.Increment(ref _snCounter);
  573. return $"{prefix}-{workOrder.MaterialCode}-{timestamp}-{counter:D4}-{randomStr}";
  574. }
  575. private string GetPrintTypePrefix(int printType)
  576. {
  577. switch (printType)
  578. {
  579. case 1:
  580. return "P";
  581. case 2:
  582. return "C";
  583. case 3:
  584. return "Q";
  585. case 4:
  586. return "B";
  587. default:
  588. return "U";
  589. }
  590. }
  591. private string GetPrintTypeName(int printType)
  592. {
  593. switch (printType)
  594. {
  595. case 1:
  596. return "产品码";
  597. case 2:
  598. return "零件码";
  599. case 3:
  600. return "合格码";
  601. case 4:
  602. return "装箱码";
  603. default:
  604. return "未知";
  605. }
  606. }
  607. #endregion
  608. }
  609. public class DateCodeConverter
  610. {
  611. // ============== 年份对照表 ==============
  612. private static readonly Dictionary<int, string> yearToCode = new Dictionary<int, string>
  613. {
  614. {2018, "1"}, {2019, "2"}, {2020, "3"}, {2021, "4"}, {2022, "5"},
  615. {2023, "6"}, {2024, "7"}, {2025, "8"}, {2026, "9"}, {2027, "A"},
  616. {2028, "B"}, {2029, "C"}, {2030, "D"}, {2031, "E"}, {2032, "F"},
  617. {2033, "G"}, {2034, "H"}, {2035, "J"}, {2036, "K"}, {2037, "L"},
  618. {2038, "M"}, {2039, "N"}, {2040, "P"}, {2041, "R"}, {2042, "S"},
  619. {2043, "T"}, {2044, "V"}, {2045, "W"}, {2046, "X"}, {2047, "Y"},
  620. {2048, "1"}, {2049, "2"}, {2050, "3"}, {2051, "4"}, {2052, "5"},
  621. {2053, "6"}, {2054, "7"}, {2055, "8"}, {2056, "9"}, {2057, "A"}
  622. };
  623. // ============== 月份对照表 ==============
  624. private static readonly Dictionary<int, string> monthToCode = new Dictionary<int, string>
  625. {
  626. {1, "1"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"},
  627. {7, "7"}, {8, "8"}, {9, "9"}, {10, "A"}, {11, "B"}, {12, "C"}
  628. };
  629. // ============== 日期对照表 ==============
  630. private static readonly Dictionary<int, string> dayToCode = new Dictionary<int, string>
  631. {
  632. {1, "1"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"}, {8, "8"}, {9, "9"},
  633. {10, "A"}, {11, "B"}, {12, "C"}, {13, "D"}, {14, "E"}, {15, "F"}, {16, "G"},
  634. {17, "H"}, {18, "J"}, {19, "K"},{20,"L"},{21, "M"}, {22, "N"}, {23, "P"}, {24, "R"},
  635. {25, "S"}, {26, "T"}, {27, "U"}, {28, "V"}, {29, "W"}, {30, "X"}, {31, "Y"}
  636. };
  637. // ============== 反向查找字典 ==============
  638. private static readonly Dictionary<string, int> codeToYear;
  639. private static readonly Dictionary<string, int> codeToMonth;
  640. private static readonly Dictionary<string, int> codeToDay;
  641. static DateCodeConverter()
  642. {
  643. // 初始化反向字典
  644. codeToYear = yearToCode
  645. .GroupBy(kv => kv.Value)
  646. .ToDictionary(g => g.Key, g => g.Last().Key);
  647. codeToMonth = monthToCode
  648. .ToDictionary(kv => kv.Value, kv => kv.Key);
  649. codeToDay = dayToCode
  650. .ToDictionary(kv => kv.Value, kv => kv.Key);
  651. }
  652. // ============== 年份相关方法 ==============
  653. /// <summary>
  654. /// 根据年份获取代码
  655. /// </summary>
  656. public static string GetYearCode(int year)
  657. {
  658. return yearToCode.TryGetValue(year, out string code) ? code : "未知年份";
  659. }
  660. /// <summary>
  661. /// 根据代码获取年份(返回最新的对应年份)
  662. /// </summary>
  663. public static int? GetYearByCode(string code)
  664. {
  665. return codeToYear.TryGetValue(code, out int year) ? year : (int?)null;
  666. }
  667. /// <summary>
  668. /// 获取所有对应某个代码的年份
  669. /// </summary>
  670. public static List<int> GetAllYearsByCode(string code)
  671. {
  672. return yearToCode
  673. .Where(kv => kv.Value == code)
  674. .Select(kv => kv.Key)
  675. .ToList();
  676. }
  677. // ============== 月份相关方法 ==============
  678. /// <summary>
  679. /// 根据月份获取代码
  680. /// </summary>
  681. public static string GetMonthCode(int month)
  682. {
  683. if (month < 1 || month > 12)
  684. return "无效月份";
  685. return monthToCode.TryGetValue(month, out string code) ? code : "未知月份";
  686. }
  687. /// <summary>
  688. /// 根据代码获取月份
  689. /// </summary>
  690. public static int? GetMonthByCode(string code)
  691. {
  692. return codeToMonth.TryGetValue(code, out int month) ? month : (int?)null;
  693. }
  694. // ============== 日期相关方法 ==============
  695. /// <summary>
  696. /// 根据日期获取代码
  697. /// </summary>
  698. public static string GetDayCode(int day)
  699. {
  700. if (day < 1 || day > 31)
  701. return "无效日期";
  702. return dayToCode.TryGetValue(day, out string code) ? code : "未知日期";
  703. }
  704. /// <summary>
  705. /// 根据代码获取日期
  706. /// </summary>
  707. public static int? GetDayByCode(string code)
  708. {
  709. return codeToDay.TryGetValue(code, out int day) ? day : (int?)null;
  710. }
  711. // ============== 完整日期转换方法 ==============
  712. /// <summary>
  713. /// 将DateTime转换为日期代码(3位字符:年份代码 + 月份代码 + 日期代码)
  714. /// </summary>
  715. public static string ConvertToDateCode(DateTime date)
  716. {
  717. string yearCode = GetYearCode(date.Year);
  718. string monthCode = GetMonthCode(date.Month);
  719. string dayCode = GetDayCode(date.Day);
  720. // 检查是否有无效的代码
  721. if (yearCode == "未知年份" || monthCode == "无效月份" || dayCode == "无效日期" || dayCode == "未知日期")
  722. {
  723. return "无效日期";
  724. }
  725. return $"{yearCode}{monthCode}{dayCode}";
  726. }
  727. /// <summary>
  728. /// 将日期代码转换为DateTime(如果有多个年份对应,返回最新的)
  729. /// </summary>
  730. public static DateTime? ConvertFromDateCode(string dateCode)
  731. {
  732. if (string.IsNullOrEmpty(dateCode) || dateCode.Length != 3)
  733. return null;
  734. string yearCode = dateCode.Substring(0, 1);
  735. string monthCode = dateCode.Substring(1, 1);
  736. string dayCode = dateCode.Substring(2, 1);
  737. var year = GetYearByCode(yearCode);
  738. var month = GetMonthByCode(monthCode);
  739. var day = GetDayByCode(dayCode);
  740. if (!year.HasValue || !month.HasValue || !day.HasValue)
  741. return null;
  742. try
  743. {
  744. return new DateTime(year.Value, month.Value, day.Value);
  745. }
  746. catch (ArgumentOutOfRangeException)
  747. {
  748. return null;
  749. }
  750. }
  751. /// <summary>
  752. /// 将日期代码转换为所有可能的DateTime列表(考虑年份重复的情况)
  753. /// </summary>
  754. public static List<DateTime> ConvertAllFromDateCode(string dateCode)
  755. {
  756. var result = new List<DateTime>();
  757. if (string.IsNullOrEmpty(dateCode) || dateCode.Length != 3)
  758. return result;
  759. string yearCode = dateCode.Substring(0, 1);
  760. string monthCode = dateCode.Substring(1, 1);
  761. string dayCode = dateCode.Substring(2, 1);
  762. var allYears = GetAllYearsByCode(yearCode);
  763. var month = GetMonthByCode(monthCode);
  764. var day = GetDayByCode(dayCode);
  765. if (allYears.Count == 0 || !month.HasValue || !day.HasValue)
  766. return result;
  767. foreach (var year in allYears)
  768. {
  769. try
  770. {
  771. result.Add(new DateTime(year, month.Value, day.Value));
  772. }
  773. catch (ArgumentOutOfRangeException)
  774. {
  775. // 跳过无效日期(如2月30日等)
  776. }
  777. }
  778. return result;
  779. }
  780. }
  781. }