From 507c540eed466aaabfc543c8a514596445d3a7af Mon Sep 17 00:00:00 2001
From: yanjinhui <3306209981@qq.com>
Date: 星期五, 10 四月 2026 14:44:34 +0800
Subject: [PATCH] Merge branch 'master' of http://115.159.85.185:8098/r/RuiShengZhiNeng/GaoPuLiTiKu

---
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/TaskErrorMessageController.cs |   23 +++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskErrorMessageService.cs            |   21 +++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/RGVLocationInfoService.cs            |    6 
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs                      |   14 +-
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskMethods.cs                        |   50 +++++++++--
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskErrorMessageService.cs          |   19 ++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_TaskErrorMessage.cs          |   55 +++++++++++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs                        |    4 
 8 files changed, 170 insertions(+), 22 deletions(-)

diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/RGVLocationInfoService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/RGVLocationInfoService.cs"
index 7057215..4e6faa9 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/RGVLocationInfoService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/RGVLocationInfoService.cs"
@@ -98,19 +98,19 @@
                     List<Dt_RGVLocationInfo> dt_RGVLocationInfos = BaseDal.QueryData(x => x.RoadwayNo == items.Key);//鏌ユ壘褰撳墠宸烽亾鍙疯揣浣�
                     if (item.LocationType == 1)
                     {
-                        rGVLocationInfo = dt_RGVLocationInfos.Where(x => x.Depth < item.Depth && x.LocationStatus == LocationStatusEnum.InStock.ObjToInt()).FirstOrDefault();//鍒ゆ柇娴呮繁搴﹁揣浣嶆槸鍚︽湁璐�
+                        rGVLocationInfo = dt_RGVLocationInfos.Where(x => x.Depth < item.Depth && x.LocationStatus != LocationStatusEnum.Free.ObjToInt()).FirstOrDefault();//鍒ゆ柇娴呮繁搴﹁揣浣嶆槸鍚︽湁璐�
                         if (rGVLocationInfo != null) break;
                         return item;
                     }
                     else
                     {
-                        rGVLocationInfo = dt_RGVLocationInfos.Where(x => x.Depth < item.Depth && x.LocationStatus == LocationStatusEnum.InStock.ObjToInt()).OrderByDescending(x => x.Depth).FirstOrDefault();//鍒ゆ柇娴呮繁搴﹁揣浣嶆槸鍚︽湁璐�
+                        rGVLocationInfo = dt_RGVLocationInfos.Where(x => x.Depth < item.Depth && x.LocationStatus != LocationStatusEnum.Free.ObjToInt()).OrderByDescending(x => x.Depth).FirstOrDefault();//鍒ゆ柇娴呮繁搴﹁揣浣嶆槸鍚︽湁璐�
                         if (rGVLocationInfo != null)
                         {
                             rGVLocationInfo = dt_RGVLocationInfos.Where(x => x.Depth > rGVLocationInfo.Depth && x.LocationStatus == LocationStatusEnum.Free.ObjToInt()).OrderBy(x => x.Depth).FirstOrDefault();
                             if (rGVLocationInfo != null)
                             {
-                                if (dt_RGVLocationInfos.Where(x => x.Depth > rGVLocationInfo.Depth && x.LocationStatus == LocationStatusEnum.InStock.ObjToInt()).Any()) rGVLocationInfo = null;
+                                if (dt_RGVLocationInfos.Where(x => x.Depth > rGVLocationInfo.Depth && x.LocationStatus != LocationStatusEnum.Free.ObjToInt()).Any()) rGVLocationInfo = null;
                                 else return rGVLocationInfo;
                             }
                         }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskErrorMessageService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskErrorMessageService.cs"
new file mode 100644
index 0000000..52334c4
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskErrorMessageService.cs"
@@ -0,0 +1,19 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.BaseRepository;
+using WIDESEAWCS_Core.BaseServices;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_ITaskInfoService
+{
+    public interface ITaskErrorMessageService : IService<Dt_TaskErrorMessage>
+    {
+        /// <summary>
+        /// 浠撳偍灞�(鏁版嵁搴撹闂�)
+        /// </summary>
+        IRepository<Dt_TaskErrorMessage> Repository { get; }
+    }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs"
index 6fe4558..d8009d2 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs"
@@ -75,14 +75,14 @@
         /// </summary>
         /// <param name="wMSCancelTask">鍙栨秷浠诲姟瀹炰綋绫�</param>
         /// <returns></returns>
-         WebResponseContent CancelWMSTask(WMSCancelTask wMSCancelTask);
+        WebResponseContent CancelWMSTask(WMSCancelTask wMSCancelTask);
 
         /// <summary>
         /// 淇敼浠诲姟浼樺厛绾�
         /// </summary>
         /// <param name="updateTaskPriority"></param>
         /// <returns></returns>
-         WebResponseContent UpdateWMSTaskPriority(WMSUpdateTaskPriority updateTaskPriority);
+        WebResponseContent UpdateWMSTaskPriority(WMSUpdateTaskPriority updateTaskPriority);
 
         /// <summary>
         /// 鏍规嵁鎵樼洏鍙枫�佽捣濮嬪湴鍧�鍚慦MS璇锋眰浠诲姟
@@ -210,7 +210,7 @@
         /// <param name="taskNum">浠诲姟鍙�</param>
         /// <returns>杩斿洖澶勭悊缁撴灉</returns>
         WebResponseContent TaskStatusRecovery(int taskNum);
-        WebResponseContent ErrorTaskFeedback(Dt_Task dt_Task, bool Del);
+        WebResponseContent ErrorTaskFeedback(Dt_Task dt_Task, bool Del = false, string ErrorCode = "");
         /// <summary>
         /// 鍥炴粴浠诲姟鐘舵��
         /// </summary>
@@ -233,7 +233,7 @@
         /// <param name="deviceTypeEnum"></param>
         /// <param name="locationStatusEnum"></param>
         /// <returns></returns>
-        WebResponseContent UpdateLocationStatus(string locationCode,string palletCode, DeviceTypeEnum deviceTypeEnum, LocationStatusEnum locationStatusEnum);
+        WebResponseContent UpdateLocationStatus(string locationCode, string palletCode, DeviceTypeEnum deviceTypeEnum, LocationStatusEnum locationStatusEnum);
 
 
         WebResponseContent ModifyWMSLayoutZone(WMSUpdateLocationArea wMSUpdateLocationArea);
@@ -268,7 +268,7 @@
         /// <param name="taskCode">浠诲姟鍙�</param>
         /// <param name="containerCode">瀹瑰櫒缂栫爜</param>
         /// <returns></returns>
-        public WebResponseContent MaterialBoxInspection(string taskCode ,string containerCode);
+        public WebResponseContent MaterialBoxInspection(string taskCode, string containerCode);
 
         /// <summary>
         /// 4F鎻愬崌鏈哄嚭鍙f墭鐩樺彿涓婃姤WMS
@@ -311,7 +311,7 @@
         /// </summary>
         /// <param name="TaskCode">浠诲姟鍙�</param>
         /// <returns></returns>
-        WebResponseContent Hikvisiontaskscontinue(string TaskCode, string Address=null);
-      
+        WebResponseContent Hikvisiontaskscontinue(string TaskCode, string Address = null);
+
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_TaskErrorMessage.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_TaskErrorMessage.cs"
new file mode 100644
index 0000000..86b4813
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_TaskErrorMessage.cs"
@@ -0,0 +1,55 @@
+锘縰sing Magicodes.ExporterAndImporter.Core;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.DB.Models;
+
+namespace WIDESEAWCS_Model.Models
+{
+    [SugarTable(nameof(Dt_TaskErrorMessage), "浠诲姟寮傚父淇℃伅")]
+    public class Dt_TaskErrorMessage : BaseEntity
+    {
+        /// <summary>
+        /// 涓婚敭
+        /// </summary>
+        [ImporterHeader(Name = "涓婚敭")]
+        [ExporterHeader(DisplayName = "涓婚敭")]
+        [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")]
+        public int TaskId { get; set; }
+
+        /// <summary>
+        /// 閿欒浠g爜
+        /// </summary>
+        [ImporterHeader(Name = "閿欒浠g爜")]
+        [ExporterHeader(DisplayName = "閿欒浠g爜")]
+        [SugarColumn(IsNullable = false, ColumnDescription = "閿欒浠g爜")]
+        public int ErrorCode { get; set; }
+
+        /// <summary>
+        /// 寮傚父淇℃伅鑻辨枃
+        /// </summary>
+        [ImporterHeader(Name = "寮傚父淇℃伅鑻辨枃")]
+        [ExporterHeader(DisplayName = "寮傚父淇℃伅鑻辨枃")]
+        [SugarColumn(IsNullable = true, Length = 500, ColumnDescription = "寮傚父淇℃伅鑻辨枃")]
+        public string ErrorMessage { get; set; }
+
+        /// <summary>
+        /// 寮傚父淇℃伅
+        /// </summary>
+        [ImporterHeader(Name = "寮傚父淇℃伅")]
+        [ExporterHeader(DisplayName = "寮傚父淇℃伅")]
+        [SugarColumn(IsNullable = true, Length = 500, ColumnDescription = "寮傚父淇℃伅")]
+        public string ExceptionMessage { get; set; }
+
+        /// <summary>
+        /// 璁惧绫诲瀷锛�0鍑箰澹紝1娴峰悍锛�2鍥涘悜杞�
+        /// </summary>
+        [ImporterHeader(Name = "璁惧绫诲瀷")]
+        [ExporterHeader(DisplayName = "璁惧绫诲瀷")]
+        [SugarColumn(IsNullable = false, ColumnDescription = "璁惧绫诲瀷")]
+        public int DeviceType { get; set; }
+    }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/TaskErrorMessageController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/TaskErrorMessageController.cs"
new file mode 100644
index 0000000..2f79289
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/TaskErrorMessageController.cs"
@@ -0,0 +1,23 @@
+锘縰sing Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using WIDESEAWCS_Core;
+using WIDESEAWCS_Core.BaseController;
+using WIDESEAWCS_DTO.TaskInfo;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_WCSServer.Controllers.Task
+{
+    [Route("api/TaskErrorMessage")]
+    [ApiController]
+    public class TaskErrorMessageController : ApiBaseController<ITaskErrorMessageService, Dt_TaskErrorMessage>
+    {
+        private readonly IHttpContextAccessor _httpContextAccessor;
+        public TaskErrorMessageController(ITaskErrorMessageService service, IHttpContextAccessor httpContextAccessor) : base(service)
+        {
+            _httpContextAccessor = httpContextAccessor;
+        }
+
+    }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskErrorMessageService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskErrorMessageService.cs"
new file mode 100644
index 0000000..3815a49
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskErrorMessageService.cs"
@@ -0,0 +1,21 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.BaseRepository;
+using WIDESEAWCS_Core.BaseServices;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_TaskInfoService
+{
+    public class TaskErrorMessageService : ServiceBase<Dt_TaskErrorMessage, IRepository<Dt_TaskErrorMessage>>, ITaskErrorMessageService
+    {
+        public TaskErrorMessageService(IRepository<Dt_TaskErrorMessage> BaseDal) : base(BaseDal)
+        {
+        }
+
+        public IRepository<Dt_TaskErrorMessage> Repository => BaseDal;
+    }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskMethods.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskMethods.cs"
index b31be44..6f0807f 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskMethods.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskMethods.cs"
@@ -8,6 +8,7 @@
 using System.Reflection.Metadata;
 using System.Text;
 using System.Text.Json;
+using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using WIDESEAWCS_Common;
 using WIDESEAWCS_Common.LocationEnum;
@@ -393,12 +394,18 @@
                             }
                             if (Rgv.content.status == 5)
                             {
-                                if (task.TaskState == (int)TaskStatusEnum.Execut)
+                                task.ExceptionMessage = Rgv.content.errorReason;
+                                var Error = _taskErrorMessageService.Repository.QueryFirst(x => x.ErrorCode == Rgv.content.errorCode && x.DeviceType == (int)deviceTypeEnum);
+                                if (Error != null)
                                 {
-                                    task.TaskState = (int)TaskStatusEnum.New;
-                                    task.Remark = "鍥涘悜杞﹀弽棣堝け璐�,閲嶆柊涓嬪彂";
-                                    BaseDal.UpdateData(task);
+                                    task.ExceptionMessage = Error.ExceptionMessage;
+                                    MatchCollection matches = Regex.Matches(Rgv.content.errorReason, @"\(([^)]+)\)");
+                                    if (matches.Count > 0)
+                                        task.ExceptionMessage = ReplacePlaceholders(Rgv.content.errorReason, Error.ExceptionMessage);
+                                    ErrorTaskFeedback(task, true, Error.ErrorCode.ToString());
                                 }
+                                else
+                                    ErrorTaskFeedback(task, true);
                             }
                         }
                     }
@@ -414,6 +421,30 @@
                 _trackloginfoService.AddTrackLog(TaskDTO, content, $"{deviceName}浠诲姟鐘舵�佸弽棣�", "", "");
             }
             return content;
+        }
+        #endregion
+
+        #region 寮傚父淇℃伅杞崲
+        /// <summary>
+        /// 寮傚父淇℃伅()鍐呭杞崲
+        /// </summary>
+        /// <param name="source"></param>
+        /// <param name="targetTemplate"></param>
+        /// <returns></returns>
+        public string ReplacePlaceholders(string source, string targetTemplate)
+        {
+            // 鎻愬彇婧愬瓧绗︿覆涓殑鎵�鏈夋嫭鍙峰��
+            var values = Regex.Matches(source, @"\(([^)]+)\)")
+                              .Cast<Match>()
+                              .Select(m => m.Groups[1].Value)
+                              .ToList();
+
+            // 鏇挎崲鐩爣妯℃澘涓殑鎵�鏈� (%v)
+            int idx = 0;
+            string result = Regex.Replace(targetTemplate, @"\(\%v\)", _ =>
+                idx < values.Count ? values[idx++] : "");
+
+            return result;
         }
         #endregion
 
@@ -692,7 +723,7 @@
         }
         #endregion
         #region 澶辫触浠诲姟涓婃姤WMS骞跺垹闄や换鍔�
-        public WebResponseContent ErrorTaskFeedback(Dt_Task dt_Task, bool Del)
+        public WebResponseContent ErrorTaskFeedback(Dt_Task dt_Task, bool Del = false, string ErrorCode = "")
         {
             WebResponseContent content = new WebResponseContent();
             WMSInOutBoundCompleteFeedback boundCompleteFeedback = new WMSInOutBoundCompleteFeedback();
@@ -708,7 +739,7 @@
                     boundCompleteFeedback.fromStationCode = dt_Task.SourceAddress;
                     boundCompleteFeedback.toLocationCode = dt_Task.TargetAddress;
                     boundCompleteFeedback.status = 3;
-                    boundCompleteFeedback.custStatus = "";
+                    boundCompleteFeedback.custStatus = ErrorCode;
                     boundCompleteFeedback.memo = dt_Task.ExceptionMessage;
                     string response = HttpHelper.Post(apiInfo.ApiAddress, boundCompleteFeedback.Serialize());
                     agvContent = response.DeserializeObject<WMSReturn>();
@@ -729,15 +760,12 @@
             finally
             {
                 _trackloginfoService.AddTrackLog(boundCompleteFeedback, content, "鍑哄叆搴撲换鍔$姸鎬佸弽棣圵MS", "", "");
-                if (agvContent != null && agvContent.code == 200 && Del) BaseDal.DeleteAndMoveIntoHty(dt_Task, OperateTypeEnum.鑷姩鍒犻櫎);
+                if (agvContent != null && agvContent.code == 200 && Del)
+                    BaseDal.DeleteAndMoveIntoHty(dt_Task, OperateTypeEnum.鑷姩鍒犻櫎);
                 else BaseDal.UpdateData(dt_Task);
             }
             return content;
         }
         #endregion
-
-
-
-
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs"
index b122efb..c7efb17 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs"
@@ -57,6 +57,7 @@
         private readonly IApiInfoService _apiInfoService;
         private readonly IStationMangerService _stationMangerService;
         private readonly IStationInfoService _stationInfo;
+        private readonly ITaskErrorMessageService _taskErrorMessageService;
         private readonly IMapper _mapper;
 
         private Dictionary<string, OrderByType> _taskOrderBy = new()
@@ -76,7 +77,7 @@
         /// </summary>
         public IRepository<Dt_Task> Repository => BaseDal;
 
-        public TaskService(IRepository<Dt_Task> BaseDal, IRouterService routerService, ITaskExecuteDetailService taskExecuteDetailService, IRepository<Dt_TaskExecuteDetail> taskExecuteDetailRepository, IMapper mapper, IKLSLocationInfoService kLSLocationInfoService, IRGVLocationInfoService rGVLocationInfoService, IHKLocationInfoService hKLocationInfoService, IApiInfoService apiInfoService, ITrackloginfoService trackloginfoService, IStationMangerService stationMangerService, IStationInfoService stationInfo) : base(BaseDal)
+        public TaskService(IRepository<Dt_Task> BaseDal, IRouterService routerService, ITaskExecuteDetailService taskExecuteDetailService, IRepository<Dt_TaskExecuteDetail> taskExecuteDetailRepository, IMapper mapper, IKLSLocationInfoService kLSLocationInfoService, IRGVLocationInfoService rGVLocationInfoService, IHKLocationInfoService hKLocationInfoService, IApiInfoService apiInfoService, ITrackloginfoService trackloginfoService, IStationMangerService stationMangerService, IStationInfoService stationInfo, ITaskErrorMessageService taskErrorMessageService) : base(BaseDal)
         {
             _routerService = routerService;
             _taskExecuteDetailService = taskExecuteDetailService;
@@ -89,6 +90,7 @@
             _trackloginfoService = trackloginfoService;
             _stationMangerService = stationMangerService;
             _stationInfo = stationInfo;
+            _taskErrorMessageService = taskErrorMessageService;
         }
         public WebResponseContent ReceiveWMSTask([NotNull] List<WMSTasksDTO> taskDTOs)
         {

--
Gitblit v1.9.3