ServiceHelper.cs

本文提供了一个Windows服务管理辅助类,包括安装、卸载、启动、停止服务等功能,并详细介绍了相关的方法实现。
namespace ExtraLib.Helper
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Management;
    using System.Runtime.ConstrainedExecution;
    using System.Runtime.InteropServices;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading;

    #region 异常定义

    /// <inheritdoc />
    /// <summary>
    /// 服务不存在异常
    /// </summary>
    public class ServiceNotExistException : ApplicationException
    {
        public ServiceNotExistException() : base("服务不存在!") { }

        public ServiceNotExistException(string message) : base(message) { }
    }

    #endregion

    #region 结构定义

    /// <summary>
    /// 服务配置对象
    /// </summary>
    public struct ServiceConfig
    {
        /// <summary>
        /// 服务名称:启动和关闭服务时使用的名称,可以与显示名称相同
        /// </summary>
        public string ServiceName;
        /// <summary>
        /// 显示名称:服务列表中显示的名称
        /// </summary>
        public string DisplayName;
        /// <summary>
        /// 描述:服务列表中描述该服务的功能
        /// </summary>
        public string Description;
        /// <summary>
        /// 可执行文件的路径,可带参数
        /// <para>若路径有空格,需给路径(不含参数)套上双引号,例如:@"""C:\新建 文件夹\test.exe"" /s"</para>
        /// <para>举例说明: 要启动的服务路径为 D:\srv.exe ,启动参数为 -s ,则填写路径@"D:\srv.exe -s"</para>
        /// </summary>
        public string ExeFilePath;
        /// <summary>
        /// 启动类型:设置服务启动的方式,自动或手动等
        /// </summary>
        public ServiceStartMode StartType;
        /// <summary>
        /// 登录身份:为了避免不必要的权限问题,建议设置为LocalSystem
        /// </summary>
        public ServiceAccount Account;
        /// <summary>
        /// 登录名称
        /// </summary>
        public string Username;
        /// <summary>
        /// 登录密码
        /// </summary>
        public string Password;
        /// <summary>
        /// 依赖服务:当启动服务时同时启动依赖服务时需要设置此参数,否则设置为null
        /// </summary>
        public string[] ServicesDependedOn;
    }

    #endregion

    #region 枚举定义

    /// <summary>
    /// 服务状态枚举。用于遍历从属服务API
    /// </summary>
    public enum EnumServiceState
    {
        Active = 1,
        InActive = 2,
        All = 3
    }

    #endregion

    /// <summary>
    /// Windows 服务辅助类
    /// </summary>
    public static class ServiceHelper
    {
        /// <summary>
        /// 超时等待时间(秒)
        /// </summary>
        public static int TimeOut = 30;
        /// <summary>
        /// 当前工作目录
        /// </summary>
        public static string CurrentDirectory => AppDomain.CurrentDomain.BaseDirectory;

        #region 日志方法
        static EventLog _eventLog;
        public static EventLog EventLog => _eventLog ?? (_eventLog = new EventLog());
        /// <summary>
        /// 日志记录
        /// </summary>
        /// <param name="serviceName">服务名</param>
        /// <param name="contents">日志内容</param>
        public static void Log(string serviceName, string contents)
        {
            var msg = $"{contents}\r\n";
            Console.WriteLine(msg);
            EventLog.Source = serviceName;
            EventLog.WriteEntry(msg);
        }

        #endregion

        #region 服务管理
        /// <summary>
        /// 安装服务
        /// </summary>
        /// <param name="config">服务配置对象,描述了服务相关的配置信息</param>
        public static void Install(ServiceConfig config)
        {
            var scm = OpenScManager();

            var service = IntPtr.Zero;
            try
            {
                service = Win32Class.CreateService(
                    scm,
                    config.ServiceName,
                    config.DisplayName,
                    Win32Class.SERVICE_ALL_ACCESS,
                    Win32Class.SERVICE_WIN32_OWN_PROCESS,
                    config.StartType,
                    Win32Class.SERVICE_ERROR_NORMAL,
                    config.ExeFilePath,
                    null,
                    IntPtr.Zero,
                    ProcessDependencies(config.ServicesDependedOn),
                    GetServiceAccountName(config.Account),
                    null
                    );

                if (service == IntPtr.Zero)
                {
                    if (Marshal.GetLastWin32Error() == 0x431) //ERROR_SERVICE_EXISTS
                    {
                        throw new ApplicationException("服务已存在!");
                    }
                    throw new ApplicationException("服务安装失败!");
                }

                //设置服务描述
                var sd = new Win32Class.SERVICE_DESCRIPTION();
                try
                {
                    sd.description = Marshal.StringToHGlobalUni(config.Description);
                    Win32Class.ChangeServiceConfig2(service, 1, ref sd);
                }
                finally
                {
                    Marshal.FreeHGlobal(sd.description);// 释放
                }
            }
            finally
            {
                if (service != IntPtr.Zero)
                {
                    Win32Class.CloseServiceHandle(service);
                }
                Win32Class.CloseServiceHandle(scm);
            }
        }

        /// <summary>
        /// 卸载服务
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        public static void Uninstall(string serviceName)
        {
            var scmHandle = IntPtr.Zero;
            var service = IntPtr.Zero;

            try
            {
                service = OpenService(serviceName, out scmHandle);

                StopService(service); //停止服务。里面会递归停止从属服务

                if (!Win32Class.DeleteService(service) && Marshal.GetLastWin32Error() != 0x430) //忽略已标记为删除的服务。ERROR_SERVICE_MARKED_FOR_DELETE
                {
                    throw new ApplicationException("删除服务失败!");
                }
            }
            catch (ServiceNotExistException) { } //忽略服务不存在的情况
            finally
            {
                if (service != IntPtr.Zero)
                {
                    Win32Class.CloseServiceHandle(service);
                    Win32Class.CloseServiceHandle(scmHandle);//放if里面是因为如果服务打开失败,在OpenService里就已释放SCM
                }
            }
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>成功:true,失败:false</returns>
        public static bool StartService(string serviceName)
        {
            if (!IsExists(serviceName)) return false;
            var sc = new ServiceController(serviceName);
            if (sc.Status != ServiceControllerStatus.Running && sc.Status != ServiceControllerStatus.StartPending)
            {
                sc.Start();
            }
            sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, TimeOut));
            return sc.Status == ServiceControllerStatus.Running;
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>成功:true,失败:false</returns>
        public static bool StopService(string serviceName)
        {
            bool isDone;
            var scmHandle = IntPtr.Zero;
            var service = IntPtr.Zero;
            try
            {
                service = OpenService(serviceName, out scmHandle);
                StopService(service);
                isDone = true;
            }
            catch
            {
                isDone = false;
            }
            finally
            {
                if (service != IntPtr.Zero)
                {
                    Win32Class.CloseServiceHandle(service);
                    Win32Class.CloseServiceHandle(scmHandle);
                }
            }
            return isDone;
        }

        /// <summary>
        /// 运行服务,用于安装服务后的服务调用
        /// </summary>
        /// <param name="services"> 一组 ServiceBase 实例,指示要启动的服务</param>
        public static void RunService(params ServiceBase[] services)
        {
            ServiceBase.Run(services);
        }

        /// <summary>
        /// 检查服务是否运行
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>运行:true,停止:false</returns>
        public static bool IsRunning(string serviceName)
        {
            return ServiceController.GetServices().Where(t => t.ServiceName.ToLower().Equals(serviceName.ToLower())).Any(t => t.Status == ServiceControllerStatus.Running);
        }

        /// <summary>
        /// 检查服务是否存在
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>存在:true,不存在:false</returns>
        public static bool IsExists(string serviceName)
        {
            return ServiceController.GetServices().Any(t => t.ServiceName.ToLower().Equals(serviceName.ToLower()));
        }

        /// <summary>
        /// 设置服务允许与桌面交互
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        public static void DesktopInteract(string serviceName)
        {
            var co = new ConnectionOptions { Impersonation = ImpersonationLevel.Impersonate };
            var ms = new ManagementScope(@"root/CIMV2", co);
            ms.Connect();
            using (var wmiService = new ManagementObject($"Win32_Service.Name='{serviceName}'"))
            using (var inParam = wmiService.GetMethodParameters("Change"))
            {
                inParam["DesktopInteract"] = true;
                wmiService.InvokeMethod("Change", inParam, null);
            }
        }

        #endregion

        #region 接口方法
        /// <summary>
        /// 打开服务管理器
        /// </summary>
        public static IntPtr OpenScManager()
        {
            var scm = Win32Class.OpenSCManager(null, null, Win32Class.SC_MANAGER_ALL_ACCESS);

            if (scm == IntPtr.Zero)
            {
                throw new ApplicationException("打开服务管理器失败!");
            }

            return scm;
        }

        /// <summary>
        /// 打开服务
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <param name="scManagerHandle">服务管理器句柄</param>
        public static IntPtr OpenService(string serviceName, out IntPtr scManagerHandle)
        {
            scManagerHandle = OpenScManager();

            var serviceHandle = Win32Class.OpenService(scManagerHandle, serviceName, Win32Class.SERVICE_ALL_ACCESS);

            if (serviceHandle != IntPtr.Zero) return serviceHandle;
            var errCode = Marshal.GetLastWin32Error();

            Win32Class.CloseServiceHandle(scManagerHandle); //关闭SCM

            if (errCode == 0x424) //ERROR_SERVICE_DOES_NOT_EXIST
            {
                throw new ServiceNotExistException();
            }

            throw new Win32Exception();
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="serviceHandle">服务管理器句柄</param>
        public static void StopService(IntPtr serviceHandle)
        {
            var currState = GetServiceStatus(serviceHandle);

            if (currState == ServiceControllerStatus.Stopped)
            {
                return;
            }

            if (currState != ServiceControllerStatus.StopPending)
            {
                //递归停止从属服务
                var childSvs = EnumDependentServices(serviceHandle, EnumServiceState.Active);
                if (childSvs.Length != 0)
                {
                    var scm = OpenScManager();
                    try
                    {
                        foreach (var childSv in childSvs)
                        {
                            StopService(Win32Class.OpenService(scm, childSv, Win32Class.SERVICE_STOP));
                        }
                    }
                    finally
                    {
                        Win32Class.CloseServiceHandle(scm);
                    }
                }

                var status = new Win32Class.SERVICE_STATUS();
                Win32Class.ControlService(serviceHandle, Win32Class.SERVICE_CONTROL_STOP, ref status); //发送停止指令
            }

            if (!WaitForStatus(serviceHandle, ServiceControllerStatus.Stopped, new TimeSpan(0, 0, TimeOut)))
            {
                throw new ApplicationException("停止服务失败!");
            }
        }

        /// <summary>
        /// 等候服务至目标状态
        /// </summary>
        /// <param name="serviceHandle">服务管理器句柄</param>
        /// <param name="desiredStatus">服务状态描述</param>
        /// <param name="timeout">超时时间</param>
        public static bool WaitForStatus(IntPtr serviceHandle, ServiceControllerStatus desiredStatus, TimeSpan timeout)
        {
            var startTime = DateTime.Now;

            while (GetServiceStatus(serviceHandle) != desiredStatus)
            {
                if (DateTime.Now - startTime > timeout)
                {
                    return false;
                }

                Thread.Sleep(200);
            }

            return true;
        }

        /// <summary>
        /// 遍历从属服务
        /// </summary>
        /// <param name="serviceHandle">服务管理器句柄</param>
        /// <param name="state">要遍历的服务状态(活动、非活动、全部)</param>
        public static string[] EnumDependentServices(IntPtr serviceHandle, EnumServiceState state)
        {
            var bytesNeeded = 0; //存放从属服务的空间大小,由API返回
            var numEnumerated = 0; //从属服务数,由API返回

            //先尝试以空结构获取,如获取成功说明从属服务为空,否则拿到上述俩值
            if (Win32Class.EnumDependentServices(serviceHandle, state, IntPtr.Zero, 0, ref bytesNeeded, ref numEnumerated))
            {
                return new string[0];
            }
            if (Marshal.GetLastWin32Error() != 0xEA) //仅当错误值不是大小不够(ERROR_MORE_DATA)时才抛异常
            {
                throw new Win32Exception();
            }

            //在非托管区域创建指针
            var structsStart = Marshal.AllocHGlobal(new IntPtr(bytesNeeded));
            try
            {
                //往上述指针处塞存放从属服务的结构组,每个从属服务是一个结构
                if (!Win32Class.EnumDependentServices(serviceHandle, state, structsStart, bytesNeeded, ref bytesNeeded, ref numEnumerated))
                {
                    throw new Win32Exception();
                }

                var dependentServices = new string[numEnumerated];
                var sizeOfStruct = Marshal.SizeOf(typeof(Win32Class.ENUM_SERVICE_STATUS)); //每个结构的大小
                var structsStartAsInt64 = structsStart.ToInt64();
                for (var i = 0; i < numEnumerated; i++)
                {
                    var structure = new Win32Class.ENUM_SERVICE_STATUS();
                    var ptr = new IntPtr(structsStartAsInt64 + i * sizeOfStruct); //根据起始指针、结构次序和结构大小推算各结构起始指针
                    Marshal.PtrToStructure(ptr, structure); //根据指针拿到结构
                    dependentServices[i] = structure.serviceName; //从结构中拿到服务名
                }

                return dependentServices;
            }
            finally
            {
                Marshal.FreeHGlobal(structsStart);
            }
        }

        /// <summary>
        /// 获取服务状态
        /// </summary>
        /// <param name="serviceHandle">服务管理器句柄</param>
        public static ServiceControllerStatus GetServiceStatus(IntPtr serviceHandle)
        {
            var status = new Win32Class.SERVICE_STATUS();

            if (!Win32Class.QueryServiceStatus(serviceHandle, ref status))
            {
                throw new ApplicationException("获取服务状态出错!");
            }

            return status.currentState;
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 转换帐户枚举为有效参数
        /// </summary>
        /// <param name="account">账户类型枚举</param>
        static string GetServiceAccountName(ServiceAccount account)
        {
            return account == ServiceAccount.LocalService
                ? @"NT AUTHORITY\LocalService"
                : (account == ServiceAccount.NetworkService ? @"NT AUTHORITY\NetworkService" : null);
        }

        /// <summary>
        /// 处理依赖服务参数
        /// </summary>
        /// <param name="dependencies">依赖服务参数</param>
        static string ProcessDependencies(params string[] dependencies)
        {
            if (dependencies == null || dependencies.Length == 0)
            {
                return null;
            }

            var sb = new StringBuilder();
            foreach (var s in dependencies)
            {
                sb.Append(s).Append('\0');
            }
            sb.Append('\0');

            return sb.ToString();
        }

        #endregion

        #region 嵌套类

        /// <summary>
        /// Win32 API相关
        /// </summary>
        static class Win32Class
        {
            #region 常量定义

            /// <summary>
            /// 打开服务管理器时请求的权限:全部
            /// </summary>
            public const int SC_MANAGER_ALL_ACCESS = 0xF003F;

            /// <summary>
            /// 服务类型:自有进程类服务
            /// </summary>
            public const int SERVICE_WIN32_OWN_PROCESS = 0x10;

            /// <summary>
            /// 打开服务时请求的权限:全部
            /// </summary>
            public const int SERVICE_ALL_ACCESS = 0xF01FF;

            /// <summary>
            /// 打开服务时请求的权限:停止
            /// </summary>
            public const int SERVICE_STOP = 0x20;

            /// <summary>
            /// 服务操作标记:停止
            /// </summary>
            public const int SERVICE_CONTROL_STOP = 0x1;

            /// <summary>
            /// 服务出错行为标记
            /// </summary>
            public const int SERVICE_ERROR_NORMAL = 0x1;

            #endregion

            #region API所需类和结构定义

            /// <summary>
            /// 服务状态结构体
            /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            public struct SERVICE_STATUS
            {
                public int serviceType;
                public ServiceControllerStatus currentState;
                public int controlsAccepted;
                public int win32ExitCode;
                public int serviceSpecificExitCode;
                public int checkPoint;
                public int waitHint;
            }

            /// <summary>
            /// 服务描述结构体
            /// </summary>
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct SERVICE_DESCRIPTION
            {
                public IntPtr description;
            }

            /// <summary>
            /// 服务状态结构体。遍历API会用到
            /// </summary>
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public class ENUM_SERVICE_STATUS
            {
                public string serviceName;
                public string displayName;
                public int serviceType;
                public int currentState;
                public int controlsAccepted;
                public int win32ExitCode;
                public int serviceSpecificExitCode;
                public int checkPoint;
                public int waitHint;
            }

            #endregion

            #region API定义

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool ChangeServiceConfig2(IntPtr serviceHandle, uint infoLevel, ref SERVICE_DESCRIPTION serviceDesc);

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr OpenSCManager(string machineName, string databaseName, int dwDesiredAccess);

            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, int dwDesiredAccess);

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, int dwDesiredAccess, int dwServiceType, ServiceStartMode dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword);

            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool CloseServiceHandle(IntPtr handle);

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool QueryServiceStatus(IntPtr hService, ref SERVICE_STATUS lpServiceStatus);

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool DeleteService(IntPtr serviceHandle);

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool ControlService(IntPtr hService, int dwControl, ref SERVICE_STATUS lpServiceStatus);

            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool EnumDependentServices(IntPtr serviceHandle, EnumServiceState serviceState, IntPtr bufferOfENUM_SERVICE_STATUS, int bufSize, ref int bytesNeeded, ref int numEnumerated);

            #endregion
        }

        #endregion

    }
}

[SQL: INSERT INTO issue_code_blocks (id, issue_key, component, start_line, end_line, start_offset, end_offset, msg, _task_id, _tool_id) VALUES (%(id_m0)s, %(issue_key_m0)s, %(component_m0)s, %(start_line_m0)s, %(end_line_m0)s, %(start_offset_m0)s, %(end_offset_m0) s, %(msg_m0)s, %(_task_id_m0)s, %(_tool_id_m0)s), (%(id_m1)s, %(issue_key_m1)s, %(component_m1)s, %(start_line_m1)s, %(end_line_m1)s, %(start_offset_m1)s, %(end_offset_m1)s, %(msg_m1)s, %(_task_id_m1)s, %(_tool_id_m1)s), (%(id_m2)s, %(issue_key_m2)s, %(component_m 2)s, %(start_line_m2)s, %(end_line_m2)s, %(start_offset_m2)s, %(end_offset_m2)s, %(msg_m2)s, %(_task_id_m2)s, %(_tool_id_m2)s), (%(id_m3)s, %(issue_key_m3)s, %(component_m3)s, %(start_line_m3)s, %(end_line_m3)s, %(start_offset_m3)s, %(end_offset_m3)s, %(msg_m3)s, %(_task_id_m3)s, %(_tool_id_m3)s), (%(id_m4)s, %(issue_key_m4)s, %(component_m4)s, %(start_line_m4)s, %(end_line_m4)s, %(start_offset_m4)s, %(end_offset_m4)s, %(msg_m4)s, %(_task_id_m4)s, %(_tool_id_m4)s), (%(id_m5)s, %(issue_key_m5)s, %(component_m5)s, %(start_li ne_m5)s, %(end_line_m5)s, %(start_offset_m5)s, %(end_offset_m5)s, %(msg_m5)s, %(_task_id_m5)s, %(_tool_id_m5)s), (%(id_m6)s, %(issue_key_m6)s, %(component_m6)s, %(start_line_m6)s, %(end_line_m6)s, %(start_offset_m6)s, %(end_offset_m6)s, %(msg_m6)s, %(_task_id_m6)s , %(_tool_id_m6)s), (%(id_m7)s, %(issue_key_m7)s, %(component_m7)s, %(start_line_m7)s, %(end_line_m7)s, %(start_offset_m7)s, %(end_offset_m7)s, %(msg_m7)s, %(_task_id_m7)s, %(_tool_id_m7)s), (%(id_m8)s, %(issue_key_m8)s, %(component_m8)s, %(start_line_m8)s, %(end_ line_m8)s, %(start_offset_m8)s, %(end_offset_m8)s, %(msg_m8)s, %(_task_id_m8)s, %(_tool_id_m8)s), (%(id_m9)s, %(issue_key_m9)s, %(component_m9)s, %(start_line_m9)s, %(end_line_m9)s, %(start_offset_m9)s, %(end_offset_m9)s, %(msg_m9)s, %(_task_id_m9)s, %(_tool_id_m9 )s) ON CONFLICT (id, _tool_id) DO UPDATE SET issue_key = excluded.issue_key, component = excluded.component, start_line = excluded.start_line, end_line = excluded.end_line, start_offset = excluded.start_offset, end_offset = excluded.end_offset, msg = excluded.msg, _task_id = excluded._task_id] [parameters: {'id_m0': UUID('95e27a96-e83b-415c-9840-f034af48e2f0'), 'issue_key_m0': 'AZZ_ZDC8WJsXx-KzsJ5m', 'component_m0': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m0': 379, 'end_line_m0': 379, 'start_offs et_m0': 32, 'end_offset_m0': 43, 'msg_m0': '', '_task_id_m0': '20250808_152917', '_tool_id_m0': 'SonarQube', 'id_m1': UUID('09bb7371-3bb4-487f-b308-85e274c493b8'), 'issue_key_m1': 'AZZ_ZDC8WJsXx-KzsJ5l', 'component_m1': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens /Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m1': 396, 'end_line_m1': 396, 'start_offset_m1': 25, 'end_offset_m1': 36, 'msg_m1': '', '_task_id_m1': '20250808_152917', '_tool_id_m1': 'SonarQube', 'id_m2': UUID('1895b19c-e9a9-4ff2-a67c-bfa5269524b6'), 'issu e_key_m2': 'AZZ_ZDC8WJsXx-KzsJ5k', 'component_m2': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m2': 443, 'end_line_m2': 443, 'start_offset_m2': 28, 'end_offset_m2': 35, 'msg_m2': '', '_task_id_m2': '20250808_15 2917', '_tool_id_m2': 'SonarQube', 'id_m3': UUID('4b3bbb63-402c-444d-aa65-4418211910c8'), 'issue_key_m3': 'AZZ_ZDC8WJsXx-KzsJ5j', 'component_m3': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m3': 421, 'end_line_ m3': 421, 'start_offset_m3': 28, 'end_offset_m3': 35, 'msg_m3': '', '_task_id_m3': '20250808_152917', '_tool_id_m3': 'SonarQube', 'id_m4': UUID('6abeda9e-7f46-4c80-b67a-0da154225756'), 'issue_key_m4': 'AZZ_ZDC8WJsXx-KzsJ5i', 'component_m4': 'UI/Naura.ThinFilm.UI.C omponents.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m4': 333, 'end_line_m4': 333, 'start_offset_m4': 28, 'end_offset_m4': 31, 'msg_m4': '', '_task_id_m4': '20250808_152917', '_tool_id_m4': 'SonarQube', 'id_m5': UUID('8cbab3c2-f477-4476-80c0- ca22539284e6'), 'issue_key_m5': 'AZZ_ZDC8WJsXx-KzsJ5h', 'component_m5': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m5': 294, 'end_line_m5': 294, 'start_offset_m5': 40, 'end_offset_m5': 43, 'msg_m5': '', '_task _id_m5': '20250808_152917', '_tool_id_m5': 'SonarQube', 'id_m6': UUID('19ed8cda-6021-46cf-b323-6b0fbcf43a2f'), 'issue_key_m6': 'AZZ_ZDC8WJsXx-KzsJ5f', 'component_m6': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line _m6': 28, 'end_line_m6': 28, 'start_offset_m6': 31, 'end_offset_m6': 46, 'msg_m6': '', '_task_id_m6': '20250808_152917', '_tool_id_m6': 'SonarQube', 'id_m7': UUID('2bd4c2a0-51bc-46de-927b-e6f4d3427a02'), 'issue_key_m7': 'AZZ_ZDC8WJsXx-KzsJ5e', 'component_m7': 'UI/ Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m7': 16, 'end_line_m7': 16, 'start_offset_m7': 0, 'end_offset_m7': 29, 'msg_m7': '', '_task_id_m7': '20250808_152917', '_tool_id_m7': 'SonarQube', 'id_m8': UUID('a0fd1f59 -0e51-4452-a91e-682c1f245067'), 'issue_key_m8': 'AZZ_ZDC8WJsXx-KzsJ5d', 'component_m8': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/Helper/ModuleHelper.cs', 'start_line_m8': 15, 'end_line_m8': 15, 'start_offset_m8': 0, 'end_offset_m8': 18, 'msg_m8 ': '', '_task_id_m8': '20250808_152917', '_tool_id_m8': 'SonarQube', 'id_m9': UUID('3c976f7f-258f-46e7-a2ec-05e5f51c6094'), 'issue_key_m9': 'AZZ_ZDBpWJsXx-KzsJ5Z', 'component_m9': 'UI/Naura.ThinFilm.UI.Components.PVD/Screens/Service/Chamber/ChamberTabItem/PreClean ChamberControlViewModel.cs', 'start_line_m9': 18, 'end_line_m9': 18, 'start_offset_m9': 0, 'end_offset_m9': 17, 'msg_m9': '', '_task_id_m9': '20250808_152917', '_tool_id_m9': 'SonarQube'}] (Background on this error at: https://sqlalche.me/e/20/f405) Traceback (most recent call last): File "D:\pyVenv\DataProcess\lib\site-packages\sqlalchemy\engine\base.py", line 1963, in _exec_single_context self.dialect.do_execute( File "D:\pyVenv\DataProcess\lib\site-packages\sqlalchemy\engine\default.py", line 943, in do_execute cursor.execute(statement, parameters) psycopg2.errors.InvalidColumnReference: there is no unique or exclusion constraint matching the ON CONFLICT specification
08-09
package com.haosmart.dpr.mom.service.aps.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Lists; import com.haosmart.boot.mybatisplus.model.BaseModel; import com.haosmart.boot.mybatisplus.service.impl.HaoSmartBaseServiceImpl; import com.haosmart.boot.platform.dto.response.HaoSmartUserDTO; import com.haosmart.boot.platform.feign.IUserService; import com.haosmart.btp.mdm.enumcom.YesOrNoEnum; import com.haosmart.common.foundation.context.BaseContextHolder; import com.haosmart.common.foundation.exception.BusinessException; import com.haosmart.common.foundation.http.ErrorCode; import com.haosmart.common.foundation.http.ResponseResult; import com.haosmart.common.foundation.jwt.IJwtUser; import com.haosmart.dpr.mom.component.mybatis.helper.BatchRepositoryHelper; import com.haosmart.dpr.mom.component.mybatis.helper.BatchRepositoryHelperImpl; import com.haosmart.dpr.mom.config.StrategyDefinitionConfig; import com.haosmart.dpr.mom.constant.BusinessConstants; import com.haosmart.dpr.mom.dao.aps.ScheduleShiftCalendarDao; import com.haosmart.dpr.mom.dto.aps.*; import com.haosmart.dpr.mom.dto.bs.WorkcenterShiftCalendarDTO; import com.haosmart.dpr.mom.dto.inner.InnerWorkShiftModelScheduleDTO; import com.haosmart.dpr.mom.dto.mes.cs.OperationDTO; import com.haosmart.dpr.mom.dto.mes.cs.ProcessRouteDetailsDTO; import com.haosmart.dpr.mom.enumeration.ApsConfigurationEnum; import com.haosmart.dpr.mom.enumeration.MomModuleEnum; import com.haosmart.dpr.mom.enumeration.aps.ShiftModelTypeEnum; import com.haosmart.dpr.mom.ganttchart.scheduling.ScheduleGateway; import com.haosmart.dpr.mom.ganttchart.scheduling.context.SchedulingOrder; import com.haosmart.dpr.mom.infrastructure.mdm.dto.WorkCenterDTO; import com.haosmart.dpr.mom.infrastructure.mdm.service.WorkcenterQueryService; import com.haosmart.dpr.mom.model.aps.ScheduleShiftCalendar; import com.haosmart.dpr.mom.model.aps.ScheduleTask; import com.haosmart.dpr.mom.model.om.ProductionMonthPlan; import com.haosmart.dpr.mom.service.aps.ScheduleShiftCalendarService; import com.haosmart.dpr.mom.service.aps.ShiftModelService; import com.haosmart.dpr.mom.utils.MomDateUtil; import com.haosmart.dpr.mom.utils.WeiXinUtil; import com.haosmart.dpr.mom.utils.aps.TimeUtil; import com.haosmart.dpr.mom.vo.aps.*; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.concurrent.*; import java.util.function.Function; import java.util.stream.Collectors; /** * <p> * 班次模型日程表 服务实现类 * </p> * * @author chixin * @since 2024-08-26 */ @Service public class ScheduleShiftCalendarServiceImpl extends HaoSmartBaseServiceImpl<ScheduleShiftCalendarDao, ScheduleShiftCalendar> implements ScheduleShiftCalendarService { @Resource private BatchRepositoryHelper<ScheduleShiftCalendar> batchRepositoryHelper; @Resource private WorkcenterQueryService workcenterQueryService; @Resource private ShiftModelService shiftModelService; @Resource private ScheduleGateway scheduleGateway; @Resource private ScheduleShiftCalendarDao scheduleShiftCalendarDao; @Autowired private IUserService iUserService; @Autowired private WeiXinUtil weiXinUtil; @Override @Transactional(rollbackFor = Exception.class) public void batchInsert(List<ScheduleShiftCalendar> entities) { if(CollectionUtils.isEmpty(entities)){ return; } batchRepositoryHelper.batchInsert(entities); } @Override @Transactional(rollbackFor = Exception.class) public void batchUpdate(List<ScheduleShiftCalendar> entities) { batchRepositoryHelper.batchUpdate(entities); } @Override @Transactional(rollbackFor = Exception.class) public void batchPhysicalDelete(List<ScheduleShiftCalendar> entities) { if(CollectionUtils.isEmpty(entities)){ return; } batchRepositoryHelper.batchRemove(entities); // //删除次数 // int deleteCount = entities.size()/1000; // for(int i = 0; i <= deleteCount; i++){ // List<ScheduleShiftCalendar> subList = entities.subList(i*1000,Math.min(entities.size(),(i+1)*1000)); // // } } @Override @Transactional(rollbackFor = Exception.class) public List<ScheduleShiftCalendar> create(ScheduleShiftCalendarCreateVO scheduleShiftCalendarCreateVO) { List<ScheduleShiftCalendar> resultList = new ArrayList<>(); do{ scheduleShiftCalendarCreateVO.setCalDate(scheduleShiftCalendarCreateVO.getStartCalDate()); resultList.addAll(updateById(BeanUtil.copyProperties(scheduleShiftCalendarCreateVO, ScheduleShiftCalendarUpdateVO.class))); scheduleShiftCalendarCreateVO.setStartCalDate(MomDateUtil.addOrSubtractsDate(scheduleShiftCalendarCreateVO.getStartCalDate(),1)); }while (scheduleShiftCalendarCreateVO.getStartCalDate().compareTo(scheduleShiftCalendarCreateVO.getEndCalDate())<=0); return resultList; } // @Override // public void batchCreate(ScheduleShiftCalendarCreateVO scheduleShiftCalendarCreateVO) { // List<Map<String, String>> workCenter = scheduleShiftCalendarCreateVO.getWorkCenter(); // Date startCalDate = scheduleShiftCalendarCreateVO.getStartCalDate(); // // for(Map<String, String> param : workCenter){ // scheduleShiftCalendarCreateVO.setWorkCenterCode(param.get("workCenterCode")); // scheduleShiftCalendarCreateVO.setWorkCenterName(param.get("workCenterName")); // scheduleShiftCalendarCreateVO.setStartCalDate(startCalDate); // create(scheduleShiftCalendarCreateVO); // } // } //start @Override @Transactional(rollbackFor = Exception.class) public void batchCreate(ScheduleShiftCalendarCreateVO scheduleShiftCalendarCreateVO) { List<Map<String, String>> workCenterList = scheduleShiftCalendarCreateVO.getWorkCenter(); Date startCalDate = scheduleShiftCalendarCreateVO.getStartCalDate(); Date endCalDate = scheduleShiftCalendarCreateVO.getEndCalDate(); // 收集所有日期和工作中心组合 List<Date> dates = getDateRange(startCalDate, endCalDate); List<Pair<String, String>> workCenterPairs = workCenterList.stream() .map(map -> Pair.of(map.get("workCenterCode"), map.get("workCenterName"))) .collect(Collectors.toList()); // 批量查询已有记录 ScheduleShiftCalendarQueryVO queryVO = new ScheduleShiftCalendarQueryVO(); queryVO.setStartCalDate(TimeUtil.convertedDate2LocalDateTime(startCalDate).toLocalDate()); queryVO.setEndCalDate(TimeUtil.convertedDate2LocalDateTime(endCalDate).toLocalDate()); queryVO.setWorkCenterCodeList(workCenterPairs.stream().map(Pair::getKey).collect(Collectors.toList())); queryVO.setTaskCode(BusinessConstants.DB_STR_DEFAULT); queryVO.setTaskVersion(BusinessConstants.DB_STR_DEFAULT); queryVO.setDefaultFlag(YesOrNoEnum.YES.getCode()); List<ScheduleShiftCalendarDTO> existingRecords = list(queryVO); // 按(日期, 工作中心)分组 Map<Pair<Date, String>, List<ScheduleShiftCalendarDTO>> groupByDateAndWorkCenter = existingRecords.stream() .collect(Collectors.groupingBy(dto -> Pair.of(dto.getCalDate(), dto.getWorkCenterCode()))); // 创建线程安全的集合 Queue<ScheduleShiftCalendar> toDelete = new ConcurrentLinkedQueue<>(); Queue<ScheduleShiftCalendar> toInsert = new ConcurrentLinkedQueue<>(); // 根据CPU核心数设置线程池大小(建议I/O密集型任务可设置2*核心数) int threadPoolSize = Math.min(8, Runtime.getRuntime().availableProcessors() * 2); ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize); // 使用CountDownLatch等待所有任务完成 CountDownLatch latch = new CountDownLatch(workCenterPairs.size()); workCenterPairs.forEach(workCenter -> executor.submit(() ->{ try{ String workCenterCode = workCenter.getKey(); String workCenterName = workCenter.getValue(); for (Date date : dates) { Pair<Date, String> key = Pair.of(date, workCenterCode); List<ScheduleShiftCalendarDTO> groupRecords = groupByDateAndWorkCenter.getOrDefault(key, Collections.emptyList()); // 提取不可修改的班次模型编码 List<String> cannotModifyShiftModelCodes = groupRecords.stream() .filter(dto -> !BusinessConstants.DB_STR_DEFAULT.equals(dto.getTaskVersion())) .map(ScheduleShiftCalendarDTO::getShiftModelCode) .distinct() .collect(Collectors.toList()); // 检查是否存在特殊班次模型 boolean hasSpecialShiftModel = groupRecords.stream() .anyMatch(dto -> ShiftModelTypeEnum.SPECIAL.getCode().equals(dto.getShiftModelType())); // 过滤可更新的班次模型 List<ShiftModelCreateVO> filteredShiftModels = scheduleShiftCalendarCreateVO.getShiftModelCreateVOList().stream() .filter(vo -> !cannotModifyShiftModelCodes.contains(vo.getShiftModelCode())) .collect(Collectors.toList()); // 如果存在特殊班次则只保留特殊班次 if (hasSpecialShiftModel) { filteredShiftModels = filteredShiftModels.stream() .filter(vo -> ShiftModelTypeEnum.SPECIAL.getCode().equals(vo.getShiftModelType())) .collect(Collectors.toList()); } // 生成新记录 if (!CollectionUtils.isEmpty(filteredShiftModels)) { ScheduleShiftCalendarCreateVO tempCreateVO = new ScheduleShiftCalendarCreateVO(); BeanUtil.copyProperties(scheduleShiftCalendarCreateVO, tempCreateVO); tempCreateVO.setWorkCenterCode(workCenterCode); tempCreateVO.setWorkCenterName(workCenterName); tempCreateVO.setStartCalDate(date); tempCreateVO.setEndCalDate(date); tempCreateVO.setShiftModelCreateVOList(filteredShiftModels); List<ScheduleShiftCalendar> newRecords = generateShiftCalendars(tempCreateVO, hasSpecialShiftModel); toInsert.addAll(newRecords); } // 标记可修改记录为待删除 List<ScheduleShiftCalendar> deletableRecords = groupRecords.stream() .filter(dto -> BusinessConstants.DB_STR_DEFAULT.equals(dto.getTaskVersion())) .map(dto -> BeanUtil.copyProperties(dto, ScheduleShiftCalendar.class)) .collect(Collectors.toList()); toDelete.addAll(deletableRecords); } } catch (Exception ex) { // 异常处理(可添加日志记录) throw new RuntimeException("日历新增失败", ex); } finally { latch.countDown(); // 任务完成计数 } })); try { // 等待所有任务完成(设置超时时间避免死锁) latch.await(30, TimeUnit.MINUTES); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); throw new RuntimeException("任务执行超时", ex); } finally { executor.shutdown(); // 关闭线程池 } // 批量操作数据库 if(CollectionUtil.isNotEmpty(toDelete)){ List<ScheduleShiftCalendar> delTmpList = new ArrayList<>(toDelete); // 保存本次执行结果(保持原有分批保存逻辑) for(List<ScheduleShiftCalendar> tmpList : ListUtil.split(delTmpList, 2000)) { batchPhysicalDelete(tmpList); } } if(CollectionUtil.isNotEmpty(toInsert)){ List<ScheduleShiftCalendar> addTmpList = new ArrayList<>(toInsert); // 保存本次执行结果(保持原有分批保存逻辑) for(List<ScheduleShiftCalendar> tmpList : ListUtil.split(addTmpList, 2000)) { batchInsert(tmpList); } } // 获取当前登录人 ResponseResult<HaoSmartUserDTO> userInfo = iUserService.getUserInfo(); if (userInfo.getErrcode().equals(ErrorCode.OK)&&ObjectUtil.isNotEmpty(userInfo)&&ObjectUtil.isNotEmpty(userInfo.getData())) { String prongNo = userInfo.getData().getProngNo(); weiXinUtil.sendRouteMessage(prongNo,"您创建的日历已完成,请查看"); } } /** * 生成班次日历记录 */ private List<ScheduleShiftCalendar> generateShiftCalendars(ScheduleShiftCalendarCreateVO createVO, boolean addNormalModel) { List<ScheduleShiftCalendar> result = new ArrayList<>(); Date currentDate = createVO.getStartCalDate(); List<String> shiftModelCodes = createVO.getShiftModelCreateVOList().stream() .map(ShiftModelCreateVO::getShiftModelCode) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); // 获取班次模型详情 List<ShiftModelDTO> shiftModels = shiftModelService.findByShiftModelCodeList(shiftModelCodes, null); if (addNormalModel) { shiftModels = shiftModels.stream() .filter(m -> ShiftModelTypeEnum.SPECIAL.getCode().equals(m.getShiftModelType())) .collect(Collectors.toList()); } // 构建班次映射 Map<String, Pair<String, String>> shiftMap = createVO.getShiftModelCreateVOList().stream() .flatMap(model -> model.getShiftVOList().stream() .flatMap(shiftVO -> shiftVO.getShiftCreateVOList().stream())) .collect(Collectors.toMap( ShiftCreateVO::getShiftCode, shift -> Pair.of(shift.getShiftCode(), shift.getShiftName()) )); // 生成日历记录 for (ShiftModelDTO model : shiftModels) { for (ShiftNameDTO shift : model.getShiftList()) { for (ShiftDTO shiftDetail : shift.getShiftDTOList()) { ScheduleShiftCalendar calendar = new ScheduleShiftCalendar(); calendar.setTaskCode(createVO.getTaskCode()); calendar.setTaskVersion(createVO.getTaskVersion()); calendar.setCalDate(currentDate); calendar.setWorkCenterCode(createVO.getWorkCenterCode()); calendar.setWorkCenterName(createVO.getWorkCenterName()); calendar.setShiftModelType(model.getShiftModelType()); calendar.setShiftModelCode(model.getShiftModelCode()); calendar.setShiftModelName(model.getShiftModelName()); calendar.setShiftCode(shiftDetail.getShiftCode()); calendar.setShiftName(shiftDetail.getShiftName()); // 处理跨天时间 String calDateStr = MomDateUtil.currentDateStr(currentDate, MomDateUtil.YYYYMMDD); String workStartTime = calDateStr+" "+MomDateUtil.currentDateStr(shiftDetail.getWorkStartTime(), MomDateUtil.HHMMSS); if(YesOrNoEnum.YES.getCode().equals(shiftDetail.getNextDay())){ // 如果跨天了 calDateStr = MomDateUtil.currentDateStr(MomDateUtil.addOrSubtractsDate(currentDate,1), MomDateUtil.YYYYMMDD); if(shiftDetail.getWorkStartTime().compareTo(shiftDetail.getWorkEndTime())<0){ workStartTime = calDateStr+" "+MomDateUtil.currentDateStr(shiftDetail.getWorkStartTime(), MomDateUtil.HHMMSS); } } String workEndTime = calDateStr+" "+MomDateUtil.currentDateStr(shiftDetail.getWorkEndTime(), MomDateUtil.HHMMSS); calendar.setWorkStartTime(MomDateUtil.covertToDate(workStartTime, MomDateUtil.YYYYMMDDHHMMSS)); calendar.setWorkEndTime(MomDateUtil.covertToDate(workEndTime, MomDateUtil.YYYYMMDDHHMMSS)); calendar.setTimeDuration(shiftDetail.getTimeDuration()); calendar.setDefaultFlag(StringUtils.defaultIfBlank(createVO.getDefaultFlag(), YesOrNoEnum.YES.getCode())); // 设置班组信息 Pair<String, String> teamInfo = shiftMap.get(shiftDetail.getShiftCode()); if (teamInfo != null) { calendar.setTeamCode(teamInfo.getKey()); calendar.setTeamName(teamInfo.getValue()); } result.add(calendar); } } } // 检查时间重叠 checkDateOverlapping(result); return result; } // 获取日期范围内的所有日期 public static List<Date> getDateRange(Date startDate, Date endDate) { List<Date> dates = new ArrayList<>(); Date current = startDate; while (!current.after(endDate)) { dates.add(current); current = MomDateUtil.addOrSubtractsDate(current, 1); } return dates; } //end @Transactional(rollbackFor = Exception.class) public List<ScheduleShiftCalendar> bind(ScheduleShiftCalendarCreateVO scheduleShiftCalendarCreateVO,boolean addNormalModel) { List<ScheduleShiftCalendar> scheduleShiftCalendarList = new ArrayList<>(); List<String> shiftModelCodeList = scheduleShiftCalendarCreateVO.getShiftModelCreateVOList() .stream() .map(ShiftModelCreateVO::getShiftModelCode) .filter(Objects::nonNull) .distinct().collect(Collectors.toList()); //group List<ShiftCreateVO> shiftCreateVOList = scheduleShiftCalendarCreateVO.getShiftModelCreateVOList() .stream() .flatMap(e-> e.getShiftVOList().stream().flatMap(f-> f.getShiftCreateVOList().stream())) .collect(Collectors.toList()); Map<String, Pair<String,String>> shiftMap = shiftCreateVOList.stream() .collect(Collectors.toMap(ShiftCreateVO::getShiftCode,item -> Pair.of(item.getShiftCode(),item.getShiftName()))); List<ShiftModelDTO> shiftModelList = shiftModelService.findByShiftModelCodeList(shiftModelCodeList,null); if(addNormalModel){ shiftModelList = shiftModelList.stream().filter(f-> ShiftModelTypeEnum.SPECIAL.getCode().equals(f.getShiftModelType())).collect(Collectors.toList()); } shiftModelList.forEach(e-> e.getShiftList().forEach(f-> f.getShiftDTOList().forEach(g->{ ScheduleShiftCalendar scheduleShiftCalendar = new ScheduleShiftCalendar(); scheduleShiftCalendar.setTaskCode(scheduleShiftCalendarCreateVO.getTaskCode()); scheduleShiftCalendar.setTaskVersion(scheduleShiftCalendarCreateVO.getTaskVersion()); scheduleShiftCalendar.setCalDate(scheduleShiftCalendarCreateVO.getCalDate()); scheduleShiftCalendar.setWorkCenterCode(scheduleShiftCalendarCreateVO.getWorkCenterCode()); scheduleShiftCalendar.setWorkCenterName(scheduleShiftCalendarCreateVO.getWorkCenterName()); scheduleShiftCalendar.setShiftModelType(e.getShiftModelType()); scheduleShiftCalendar.setShiftModelCode(e.getShiftModelCode()); scheduleShiftCalendar.setShiftModelName(e.getShiftModelName()); scheduleShiftCalendar.setShiftCode(g.getShiftCode()); scheduleShiftCalendar.setShiftName(g.getShiftName()); String calDateStr = MomDateUtil.currentDateStr(scheduleShiftCalendarCreateVO.getCalDate(), MomDateUtil.YYYYMMDD); String workStartTime = calDateStr+" "+MomDateUtil.currentDateStr(g.getWorkStartTime(), MomDateUtil.HHMMSS); if(YesOrNoEnum.YES.getCode().equals(g.getNextDay())){ // 如果跨天了 calDateStr = MomDateUtil.currentDateStr(MomDateUtil.addOrSubtractsDate(scheduleShiftCalendarCreateVO.getCalDate(),1), MomDateUtil.YYYYMMDD); if(g.getWorkStartTime().compareTo(g.getWorkEndTime())<0){ workStartTime = calDateStr+" "+MomDateUtil.currentDateStr(g.getWorkStartTime(), MomDateUtil.HHMMSS); } } String workEndTime = calDateStr+" "+MomDateUtil.currentDateStr(g.getWorkEndTime(), MomDateUtil.HHMMSS); scheduleShiftCalendar.setWorkStartTime(MomDateUtil.covertToDate(workStartTime,MomDateUtil.YYYYMMDDHHMMSS)); scheduleShiftCalendar.setWorkEndTime(MomDateUtil.covertToDate(workEndTime,MomDateUtil.YYYYMMDDHHMMSS)); scheduleShiftCalendar.setTimeDuration(g.getTimeDuration()); if(StringUtils.isBlank(scheduleShiftCalendarCreateVO.getDefaultFlag())){ scheduleShiftCalendar.setDefaultFlag(YesOrNoEnum.YES.getCode()); } //班组 Pair<String,String> teamPair = shiftMap.get(g.getShiftCode()); if(ObjectUtil.isNotNull(teamPair)){ scheduleShiftCalendar.setTeamCode(teamPair.getKey()); scheduleShiftCalendar.setShiftName(teamPair.getValue()); } scheduleShiftCalendarList.add(scheduleShiftCalendar); }))); //校验时间重叠;因为涉及到跨天日期,所以在此处才校验 checkDateOverlapping(scheduleShiftCalendarList); if(!CollectionUtils.isEmpty(scheduleShiftCalendarList)){ batchInsert(scheduleShiftCalendarList); } return scheduleShiftCalendarList; } /** * 校验时间重叠 * @param scheduleShiftCalendarList scheduleShiftCalendarList */ private void checkDateOverlapping(List<ScheduleShiftCalendar> scheduleShiftCalendarList) { for(int i = 0; i<scheduleShiftCalendarList.size();i++){ Date start1 = scheduleShiftCalendarList.get(i).getWorkStartTime(); Date end1 = scheduleShiftCalendarList.get(i).getWorkEndTime(); for(int j = i+1; j<scheduleShiftCalendarList.size();j++){ Date start2 = scheduleShiftCalendarList.get(j).getWorkStartTime(); Date end2 = scheduleShiftCalendarList.get(j).getWorkEndTime(); if(MomDateUtil.isOverlapping(start1,end1,start2,end2)){ throw BusinessException.e(ErrorCode.ERROR,"日历绑定失败,班次模型中时间段%s-%s与时间段%s-%s有重叠" ,MomDateUtil.currentDateStr(start1, MomDateUtil.HHMMSS) ,MomDateUtil.currentDateStr(end1, MomDateUtil.HHMMSS) ,MomDateUtil.currentDateStr(start2, MomDateUtil.HHMMSS) ,MomDateUtil.currentDateStr(end2, MomDateUtil.HHMMSS)); } } } } @Override @Transactional(rollbackFor = Exception.class) public List<ScheduleShiftCalendar> updateById(ScheduleShiftCalendarUpdateVO updateVO) { updateVO.setCalDate(updateVO.getStartCalDate()); ScheduleShiftCalendarQueryVO vo = new ScheduleShiftCalendarQueryVO(); vo.setCalDate(updateVO.getCalDate()); vo.setWorkCenterCode(updateVO.getWorkCenterCode()); vo.setDefaultFlag(YesOrNoEnum.YES.getCode()); List<ScheduleShiftCalendarDTO> list = list(vo); // 可以修改的列表 List<ScheduleShiftCalendarDTO> canModifyList = list.stream().filter(f->BusinessConstants.DB_STR_DEFAULT.equals(f.getTaskVersion())).collect(Collectors.toList()); // 不可修改的列表 List<ScheduleShiftCalendarDTO> cannotModifyList = list.stream().filter(f->!BusinessConstants.DB_STR_DEFAULT.equals(f.getTaskVersion())).collect(Collectors.toList()); // 不可以修改的已保存的班次模型code List<String> cannotModifySaveShiftModelCodeList = cannotModifyList.stream().map(ScheduleShiftCalendarDTO::getShiftModelCode).distinct().collect(Collectors.toList()); // 本次修改的班次模型code List<String> updateShiftModelCodeList = updateVO.getShiftModelCreateVOList().stream().map(ShiftModelCreateVO::getShiftModelCode).distinct().collect(Collectors.toList()); // 去除不可修改的班次模型 List<String> canModifyShiftModelCodeList = updateShiftModelCodeList.stream().filter(f->!cannotModifySaveShiftModelCodeList.contains(f)).collect(Collectors.toList()); List<ShiftModelCreateVO> sourceList = updateVO.getShiftModelCreateVOList(); List<ShiftModelCreateVO> canModifySourceList = sourceList.stream().filter(item->canModifyShiftModelCodeList.contains(item.getShiftModelCode())).collect(Collectors.toList()); Map<String,ShiftModelCreateVO> shiftModelMap = canModifySourceList.stream().collect(Collectors.toMap(ShiftModelCreateVO::getShiftModelCode, Function.identity())); // 先删除 batchPhysicalDelete(BeanUtil.copyToList(canModifyList, ScheduleShiftCalendar.class)); // 再保存 List<ShiftModelCreateVO> shiftModelCreateVOList = canModifyShiftModelCodeList.stream().map(m->{ ShiftModelCreateVO shiftModelCreateVO = new ShiftModelCreateVO(); shiftModelCreateVO.setShiftModelCode(m); ShiftModelCreateVO resourceShiftModelCreateVO = shiftModelMap.get(m); shiftModelCreateVO.setShiftVOList(resourceShiftModelCreateVO.getShiftVOList()); return shiftModelCreateVO; }).collect(Collectors.toList()); updateVO.setShiftModelCreateVOList(shiftModelCreateVOList); return bind(updateVO,list.stream().anyMatch(m->ShiftModelTypeEnum.SPECIAL.getCode().equals(m.getShiftModelType()))); } @Override @Transactional(rollbackFor = Exception.class) public void updateEffectAndDelInvalid(List<ScheduleShiftCalendarDTO> currentScheduleVersionCalendarList, List<ScheduleShiftCalendarDTO> defalutCalendarList, List<ScheduleShiftCalendarDTO> otherScheduleVersionCalendarList ) { // 删除版本未使用日历数据数据 List<ScheduleShiftCalendarDTO> delCalendarList = currentScheduleVersionCalendarList.stream().filter(e->!defalutCalendarList.contains(e)).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(delCalendarList)){ otherScheduleVersionCalendarList.addAll(delCalendarList); } if(!CollectionUtils.isEmpty(defalutCalendarList)){ // 查询是否有默认的数据,先删除 后更新 Date minCalDate = defalutCalendarList.stream().min(Comparator.comparing(ScheduleShiftCalendarDTO::getCalDate)) .orElseThrow(()->BusinessException.e(ErrorCode.ERROR,"日历数据错误")).getCalDate(); Date maxCalDate = defalutCalendarList.stream().max(Comparator.comparing(ScheduleShiftCalendarDTO::getCalDate)) .orElseThrow(()->BusinessException.e(ErrorCode.ERROR,"日历数据错误")).getCalDate(); List<String> workcenterList = defalutCalendarList.stream().map(ScheduleShiftCalendarDTO::getWorkCenterCode).distinct().collect(Collectors.toList()); ScheduleShiftCalendarQueryVO vo = new ScheduleShiftCalendarQueryVO(); vo.setStartCalDate(TimeUtil.convertedDate2LocalDateTime(minCalDate).toLocalDate()); vo.setEndCalDate(TimeUtil.convertedDate2LocalDateTime(maxCalDate).toLocalDate()); vo.setWorkCenterCodeList(workcenterList); vo.setTaskCode(BusinessConstants.DB_STR_DEFAULT); vo.setDefaultFlag(YesOrNoEnum.YES.getCode()); List<ScheduleShiftCalendarDTO> defaultList = list(vo); otherScheduleVersionCalendarList.addAll(defaultList); } if(!CollectionUtils.isEmpty(otherScheduleVersionCalendarList)){ batchPhysicalDelete(BeanUtil.copyToList(otherScheduleVersionCalendarList, ScheduleShiftCalendar.class)); } if(!CollectionUtils.isEmpty(defalutCalendarList)){ batchUpdate(BeanUtil.copyToList(defalutCalendarList, ScheduleShiftCalendar.class)); } } @Override public List<ScheduleShiftCalendarDTO> list(ScheduleShiftCalendarQueryVO scheduleShiftCalendarQueryVO) { List<ScheduleShiftCalendar> list = super.list(assembleQueryWrapper(scheduleShiftCalendarQueryVO)); return BeanUtil.copyToList(list, ScheduleShiftCalendarDTO.class); } @Override public List<WorkcenterShiftCalendarDTO> query(String taskCode, String taskVersion,Pair<LocalDate,LocalDate> datePair, List<String> workCenterCodeList) { // 排程开始日期 LocalDate startDate = datePair.getKey(); // 排程结束日期 LocalDate endDate = datePair.getValue(); //当前版本日历数据 List<ScheduleShiftCalendarDTO> versionDataList = findScheduleShiftCalendarList(taskCode,taskVersion,startDate,endDate,workCenterCodeList); Map<Pair<String,String>,List<ScheduleShiftCalendarDTO>> mapping = versionDataList.stream().collect(Collectors.groupingBy(d->Pair.of(d.getWorkCenterCode(),d.getWorkCenterName()))); //结果数据组装 List<WorkcenterShiftCalendarDTO> resultList = new ArrayList<>(); mapping.forEach((k,v)->{ WorkcenterShiftCalendarDTO workCenter = new WorkcenterShiftCalendarDTO(); workCenter.setWorkcenterCode(k.getKey()); workCenter.setWorkcenterName(k.getValue()); workCenter.setScheduleShiftCalendarList(v); resultList.add(workCenter); }); return resultList; } @Override @Transactional(rollbackFor = Exception.class) public void syncCalendar(ScheduleTask scheduleTask) { String taskVersion = "0"; //结果 List<ScheduleShiftCalendar> resultList = new ArrayList<>(); // 获取所有工作中心 List<WorkCenterDTO> workCenterList = workcenterQueryService.findAll(); //遍历树结构,获取叶子节点工作中心数据 List<WorkCenterDTO> leafNodeList = workcenterQueryService.findLeafNodeList(); leafNodeList.addAll(workCenterList); List<ScheduleShiftCalendar> list = getGeneralCalendarListForSync(scheduleTask); //当前workCenter-日历Map Map<Date, Map<String, List<ScheduleShiftCalendar>>> currentWorkCenterMapping = list.stream().collect(Collectors.groupingBy(ScheduleShiftCalendar::getCalDate, Collectors.groupingBy(ScheduleShiftCalendar::getWorkCenterCode))); //循环最下层的子节点 List<String> workCenterCodeList = leafNodeList.stream().map(WorkCenterDTO::getWorkCenterCode).collect(Collectors.toList()); //查询已存在日历 QueryWrapper<ScheduleShiftCalendar> scheduleShiftCalendarQueryWrapper = new QueryWrapper<>(); scheduleShiftCalendarQueryWrapper.lambda().in(ScheduleShiftCalendar::getWorkCenterCode,workCenterCodeList) .eq(ScheduleShiftCalendar::getDelFlag,BaseModel.DEL_FLAG_NORMAL); List<ScheduleShiftCalendar> alCalendarList = super.list(scheduleShiftCalendarQueryWrapper); Map<Pair<String, Date>, List<ScheduleShiftCalendar>> calendarMap = alCalendarList.stream().collect(Collectors.groupingBy(i -> Pair.of(i.getWorkCenterCode(), i.getCalDate()))); for(WorkCenterDTO workCenter:leafNodeList){ String workCenterCode = workCenter.getWorkCenterCode(); Long parentId = workCenter.getParentId(); if(ObjectUtil.isEmpty(parentId)){ continue; } //循环查日历 List<ScheduleShiftCalendar> calendarList = new ArrayList<>(); for(Date key:currentWorkCenterMapping.keySet()){ Map<String, List<ScheduleShiftCalendar>> stringListMap = currentWorkCenterMapping.get(key); List<ScheduleShiftCalendar> tmpList = loop2FindCalendar(workCenterCode,parentId,workCenterList,stringListMap); calendarList.addAll(tmpList); } //将查到的日历批量复制 List<ScheduleShiftCalendar> copyCalendarList = Lists.newArrayList(); for(ScheduleShiftCalendar source:calendarList){ if(ObjectUtil.isNotEmpty(calendarMap.get(Pair.of(workCenterCode,source.getCalDate())))){ continue; } ScheduleShiftCalendar calendar = new ScheduleShiftCalendar(); calendar.setTaskCode(scheduleTask.getTaskCode()); calendar.setTaskVersion(taskVersion); calendar.setWorkCenterCode(workCenterCode); calendar.setWorkCenterName(workCenter.getWorkCenterName()); calendar.setDefaultFlag(YesOrNoEnum.YES.getCode()); calendar.setShiftName(source.getShiftName()); calendar.setShiftCode(source.getShiftCode()); calendar.setTeamName(source.getTeamName()); calendar.setTeamCode(source.getTeamCode()); calendar.setCalDate(source.getCalDate()); calendar.setShiftModelType(source.getShiftModelType()); calendar.setShiftModelCode(source.getShiftModelCode()); calendar.setShiftModelName(source.getShiftModelName()); calendar.setWorkStartTime(source.getWorkStartTime()); calendar.setWorkEndTime(source.getWorkEndTime()); calendar.setTimeDuration(source.getTimeDuration()); copyCalendarList.add(calendar); } resultList.addAll(copyCalendarList); } for (List<ScheduleShiftCalendar> calendarTmp : ListUtil.split(resultList, 2000)) { super.saveBatch(calendarTmp); } } private List<ScheduleShiftCalendarDTO> findScheduleShiftCalendarList(String taskCode,String taskVersion, LocalDate startDate,LocalDate endDate, List<String> workCenterCode){ ScheduleShiftCalendarQueryVO vo = new ScheduleShiftCalendarQueryVO(); vo.setTaskCode(taskCode); vo.setTaskVersion(taskVersion); vo.setStartCalDate(startDate); vo.setEndCalDate(endDate); vo.setWorkCenterCodeList(workCenterCode); // 查询时间范围内所有日历 return list(vo); } @Override public int countByShiftModelCode(String shiftModelCode) { LambdaQueryWrapper<ScheduleShiftCalendar> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ScheduleShiftCalendar::getShiftModelCode,shiftModelCode) .eq(ScheduleShiftCalendar::getDelFlag,BaseModel.DEL_FLAG_NORMAL); return super.count(queryWrapper); } @Override public Map<String,List<CalDateShiftCalendarDTO>> findInfos(ScheduleShiftCalendarQueryVO vo) { // 当前月开始第一天 vo.setStartCalDate(vo.getCalDateOfMonth().with(TemporalAdjusters.firstDayOfMonth())); // 当前月最后一天 vo.setEndCalDate(vo.getCalDateOfMonth().with(TemporalAdjusters.lastDayOfMonth())); vo.setDefaultFlag(YesOrNoEnum.YES.getCode()); List<ScheduleShiftCalendarDTO> list = list(vo); return assembleSearchResult(list); } @Override public Pair<String,Map<String,List<CalDateShiftCalendarDTO>>> findWiInfoList(ScheduleShiftCalendarQueryVO vo) { if(ObjectUtil.isNull(vo.getCalDateOfMonth())){ vo.setCalDateOfMonth(LocalDate.now()); } LocalDate startDate = vo.getCalDateOfMonth().with(TemporalAdjusters.firstDayOfMonth()) ; LocalDate endDate = vo.getCalDateOfMonth().with(TemporalAdjusters.lastDayOfMonth()); //当前版本日历数据 List<ScheduleShiftCalendarDTO> versionDataList = findScheduleShiftCalendarList(vo.getTaskCode(), vo.getTaskVersion(),startDate,endDate, Lists.newArrayList(vo.getWorkCenterCode())); Map<String,List<CalDateShiftCalendarDTO>> value = assembleSearchResult(versionDataList); return Pair.of(TimeUtil.convertedLocalDate2String(vo.getCalDateOfMonth()),value); } /** * 拼装查询结构数据 * @param list 日历查询结果 * @return 返回页面结果 */ private Map<String,List<CalDateShiftCalendarDTO>> assembleSearchResult(List<ScheduleShiftCalendarDTO> list){ List<String> shiftModelCodeList = list.stream().map(ScheduleShiftCalendarDTO::getShiftModelCode).distinct().collect(Collectors.toList()); List<ShiftModelDTO> shiftModelDTOList = shiftModelService.findByShiftModelCodeList(shiftModelCodeList,null); Map<Date, List<ScheduleShiftCalendarDTO>> map = list.stream().collect(Collectors.groupingBy(ScheduleShiftCalendarDTO::getCalDate)); Map<String,List<CalDateShiftCalendarDTO>> resultMap = new HashMap<>(16); map.forEach((k,v)->{ Map<CalDateShiftCalendarDTO,List<ScheduleShiftCalendarDTO>> modelShiftMap = v.stream().collect(Collectors.groupingBy(e->{ CalDateShiftCalendarDTO calDateShiftCalendarDTO = new CalDateShiftCalendarDTO(); if(!BusinessConstants.DB_STR_DEFAULT.equals(e.getTaskCode()) && !BusinessConstants.DB_STR_DEFAULT.equals(e.getTaskVersion())){ calDateShiftCalendarDTO.setTaskCode(e.getTaskCode()); calDateShiftCalendarDTO.setTaskVersion(e.getTaskVersion()); } calDateShiftCalendarDTO.setShiftModelCode(e.getShiftModelCode()); calDateShiftCalendarDTO.setShiftModelName(e.getShiftModelName()); calDateShiftCalendarDTO.setDefaultFlag(e.getDefaultFlag()); calDateShiftCalendarDTO.setShiftModelType(shiftModelDTOList.stream() .filter(f->f.getShiftModelCode().equals(e.getShiftModelCode())) .findFirst().orElse(new ShiftModelDTO()).getShiftModelType()); return calDateShiftCalendarDTO; })); List<CalDateShiftCalendarDTO> resultList = new ArrayList<>(); modelShiftMap.forEach((obj,calendarList)->{ long timeDuration = calendarList.stream().mapToLong(ScheduleShiftCalendarDTO::getTimeDuration).sum(); obj.setTimeDuration(timeDuration/60000); resultList.add(obj); List<CalDateShiftCalendarDTO> calDateShiftCalendarDTOList = resultList.stream() .sorted(Comparator.comparing(CalDateShiftCalendarDTO::getShiftModelType)) .collect(Collectors.toList()); String dateKey = TimeUtil.convertedLocalDate2String(TimeUtil.convertedDate2LocalDateTime(k).toLocalDate()); // 赋值 resultMap.computeIfPresent(dateKey, (key, value) -> calDateShiftCalendarDTOList); // 初始化 resultMap.computeIfAbsent(dateKey, key -> calDateShiftCalendarDTOList); }); }); return resultMap; } @Override @Transactional(rollbackFor = Exception.class) public void deleteByCalDate(String startCalDate,String endCalDate,String workCenterCode) { // 删除非版本日历 ScheduleShiftCalendarQueryVO scheduleShiftCalendarQueryVO = new ScheduleShiftCalendarQueryVO(); scheduleShiftCalendarQueryVO.setStartCalDate(TimeUtil.convertedString2LocalDate(startCalDate)); scheduleShiftCalendarQueryVO.setEndCalDate(TimeUtil.convertedString2LocalDate(endCalDate)); scheduleShiftCalendarQueryVO.setWorkCenterCode(workCenterCode); scheduleShiftCalendarQueryVO.setTaskCode(BusinessConstants.DB_STR_DEFAULT); scheduleShiftCalendarQueryVO.setTaskVersion(BusinessConstants.DB_STR_DEFAULT); scheduleShiftCalendarQueryVO.setDefaultFlag(YesOrNoEnum.YES.getCode()); List<ScheduleShiftCalendarDTO> list = list(scheduleShiftCalendarQueryVO); batchPhysicalDelete(BeanUtil.copyToList(list, ScheduleShiftCalendar.class)); } @Override @Transactional(rollbackFor = Exception.class) public void wiCalendarInit(ScheduleTask scheduleTask,String taskVersion,List<String> sourceCodeList) { Set<String> stationCode = getStationCodeList(scheduleTask,sourceCodeList); List<ScheduleShiftCalendar> resultList = wiCalendarInitDataSearch2(scheduleTask, taskVersion,stationCode); super.saveBatch(resultList); } @Override @Transactional(rollbackFor = Exception.class) public void wiCalendarUpdate(ScheduleTask scheduleTask,String taskVersion,List<String> sourceCodeList) { Set<String> stationSet = new HashSet<>(); Set<String> stationCode = getStationCodeList(scheduleTask,sourceCodeList); //获取日历下的所有工位 List<String> stationCodeDb = scheduleShiftCalendarDao.getStationCode(scheduleTask.getTaskCode(),taskVersion); //剔除 stationCode.forEach(item->{ if(!stationCodeDb.contains(item)){ stationSet.add(item); } }); if(CollectionUtils.isEmpty(stationSet)){ return; } List<ScheduleShiftCalendar> resultList = wiCalendarInitDataSearch2(scheduleTask, taskVersion,stationSet); super.saveBatch(resultList); } public List<ScheduleShiftCalendar> wiCalendarInitDataSearch2(ScheduleTask scheduleTask,String taskVersion,Set<String> stationCode) { //结果 List<ScheduleShiftCalendar> resultList = new ArrayList<>(); // 获取所有工作中心 List<WorkCenterDTO> workCenterList = workcenterQueryService.findAll(); //遍历树结构,获取叶子节点工作中心数据 List<WorkCenterDTO> leafNodeList = workcenterQueryService.findLeafNodeList(); leafNodeList = leafNodeList.stream().filter(f->stationCode.contains(f.getWorkCenterCode())).collect(Collectors.toList()); List<ScheduleShiftCalendar> list = getGeneralCalendarList(scheduleTask); //当前workCenter-日历Map Map<String,List<ScheduleShiftCalendar>> currentWorkCenterMapping = list.stream().collect(Collectors.groupingBy(ScheduleShiftCalendar::getWorkCenterCode)); //循环最下层的子节点 for(WorkCenterDTO workCenter:leafNodeList){ String workCenterCode = workCenter.getWorkCenterCode(); Long parentId = workCenter.getParentId(); //循环查日历 List<ScheduleShiftCalendar> calendarList = loop2FindCalendar(workCenterCode,parentId,workCenterList,currentWorkCenterMapping); //将查到的日历批量复制 List<ScheduleShiftCalendar> copyCalendarList = Lists.newArrayList(); for(ScheduleShiftCalendar source:calendarList){ ScheduleShiftCalendar calendar = new ScheduleShiftCalendar(); calendar.setTaskCode(scheduleTask.getTaskCode()); calendar.setTaskVersion(taskVersion); calendar.setWorkCenterCode(workCenterCode); calendar.setWorkCenterName(workCenter.getWorkCenterName()); calendar.setDefaultFlag(YesOrNoEnum.NO.getCode()); calendar.setShiftName(source.getShiftName()); calendar.setShiftCode(source.getShiftCode()); calendar.setTeamName(source.getTeamName()); calendar.setTeamCode(source.getTeamCode()); calendar.setCalDate(source.getCalDate()); calendar.setShiftModelType(source.getShiftModelType()); calendar.setShiftModelCode(source.getShiftModelCode()); calendar.setShiftModelName(source.getShiftModelName()); calendar.setWorkStartTime(source.getWorkStartTime()); calendar.setWorkEndTime(source.getWorkEndTime()); calendar.setTimeDuration(source.getTimeDuration()); copyCalendarList.add(calendar); } resultList.addAll(copyCalendarList); } return resultList; } private List<ScheduleShiftCalendar> getGeneralCalendarList(ScheduleTask scheduleTask){ QueryWrapper<ScheduleShiftCalendar> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda() .eq(ScheduleShiftCalendar::getTaskCode,BusinessConstants.DB_STR_DEFAULT) .eq(ScheduleShiftCalendar::getTaskVersion,BusinessConstants.DB_STR_DEFAULT) .ge(ScheduleShiftCalendar::getCalDate,scheduleTask.getStartDate()) .le(ScheduleShiftCalendar::getCalDate,MomDateUtil.addOrSubtractsMonth(scheduleTask.getStartDate(),4)); return super.list(queryWrapper); } private List<ScheduleShiftCalendar> getGeneralCalendarListForSync(ScheduleTask scheduleTask){ QueryWrapper<ScheduleShiftCalendar> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda() .eq(ScheduleShiftCalendar::getTaskCode,BusinessConstants.DB_STR_DEFAULT) .eq(ScheduleShiftCalendar::getTaskVersion,BusinessConstants.DB_STR_DEFAULT) .ge(ScheduleShiftCalendar::getCalDate, DateUtil.format(scheduleTask.getStartDate(),"yyyy-MM-dd")) .le(ScheduleShiftCalendar::getCalDate,DateUtil.format(scheduleTask.getEndDate(),"yyyy-MM-dd")); return super.list(queryWrapper); } private List<ScheduleShiftCalendar> loop2FindCalendar(String workCenterCode,Long parentId, List<WorkCenterDTO> workCenterList, Map<String,List<ScheduleShiftCalendar>> currentWorkCenterMapping){ List<ScheduleShiftCalendar> calendarList =currentWorkCenterMapping.get(workCenterCode); if(CollectionUtil.isEmpty(calendarList)){ //找上级 for(WorkCenterDTO parentWorkCenter :workCenterList){ if(parentId.compareTo(parentWorkCenter.getId())==0){ workCenterCode = parentWorkCenter.getWorkCenterCode(); parentId = parentWorkCenter.getParentId(); return loop2FindCalendar(workCenterCode,parentId,workCenterList,currentWorkCenterMapping); } } } return calendarList; } @Override @Transactional(rollbackFor = Exception.class) public void wiCalendarCopy(String taskCode, String sourceTaskVersion, String taskVersion) { // 查询原版本日历信息 QueryWrapper<ScheduleShiftCalendar> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(ScheduleShiftCalendar::getTaskCode, taskCode).eq(ScheduleShiftCalendar::getTaskVersion, sourceTaskVersion); List<ScheduleShiftCalendar> list = list(queryWrapper); list.forEach(e->{ e.setTaskVersion(taskVersion); e.setId(null); e.setVersion(null); }); batchRepositoryHelper.batchInsert(list); } @Override @Transactional(rollbackFor = Exception.class) public void delete(String taskCode) { scheduleShiftCalendarDao.deleteData(taskCode); } @Override @Transactional(rollbackFor = Exception.class) public void wiUpdate(ScheduleShiftCalendarWiUpdateVO scheduleShiftCalendarWiUpdateVO) { ScheduleShiftCalendarQueryVO vo = new ScheduleShiftCalendarQueryVO(); vo.setStartCalDate(scheduleShiftCalendarWiUpdateVO.getStartCalDate()); vo.setEndCalDate(scheduleShiftCalendarWiUpdateVO.getEndCalDate()); vo.setWorkCenterCode(scheduleShiftCalendarWiUpdateVO.getWorkCenterCode()); List<ScheduleShiftCalendarDTO> list = list(vo); // 删除列表 List<String> deleteShiftModelCodeList= scheduleShiftCalendarWiUpdateVO.getChangeEntries().getDeleteItems().stream() .map(ShiftModelCreateVO::getShiftModelCode).distinct().collect(Collectors.toList()); // 时间重叠校验列表 List<ScheduleShiftCalendar> checkList = new ArrayList<>(); if(!CollectionUtils.isEmpty(deleteShiftModelCodeList)){ // 删除数据列表 List<ScheduleShiftCalendarDTO> deleteList = list.stream().filter(e-> deleteShiftModelCodeList.contains(e.getShiftModelCode())) .collect(Collectors.toList()); // 锁定不能删除列表,增加到校验列表中 checkList.addAll(BeanUtil.copyToList(list.stream().filter(e->YesOrNoEnum.YES.getCode().equals(e.getDefaultFlag())) .collect(Collectors.toList()), ScheduleShiftCalendar.class)); // 删除 batchPhysicalDelete(BeanUtil.copyToList(deleteList, ScheduleShiftCalendar.class)); // 未修改列表 List<ScheduleShiftCalendarDTO> nochangeList = list.stream().filter(f->!deleteShiftModelCodeList.contains(f.getShiftModelCode())).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(nochangeList)){ checkList.addAll(BeanUtil.copyToList(nochangeList, ScheduleShiftCalendar.class)); } } // 新增列表 List<ShiftModelCreateVO> increasedItems = scheduleShiftCalendarWiUpdateVO.getChangeEntries().getIncreasedItems(); if(!CollectionUtils.isEmpty(increasedItems)){ // 再保存 ScheduleShiftCalendarCreateVO scheduleShiftCalendarCreateVO = BeanUtil.copyProperties(scheduleShiftCalendarWiUpdateVO, ScheduleShiftCalendarCreateVO.class); scheduleShiftCalendarCreateVO.setDefaultFlag(YesOrNoEnum.NO.getCode()); scheduleShiftCalendarCreateVO.setShiftModelCreateVOList(increasedItems); checkList.addAll(create(scheduleShiftCalendarCreateVO)); } // 时间重叠校验 checkDateOverlapping(checkList); } @Override public List<InnerWorkShiftModelScheduleDTO> findByWorkcenterCodeAndCalDate(String workcenterCode, String calDate) { return baseMapper.findByWorkcenterCodeAndCalDate(workcenterCode, calDate); } @Override public List<InnerWorkShiftModelScheduleDTO> findListByShiftModelCodeAndWorkTime(String shiftModelCode, String calDate) { ScheduleShiftCalendarQueryVO scheduleShiftCalendarQueryVO = new ScheduleShiftCalendarQueryVO(); scheduleShiftCalendarQueryVO.setShiftModelCode(shiftModelCode); scheduleShiftCalendarQueryVO.setCalDateStr(calDate); return BeanUtil.copyToList(list(scheduleShiftCalendarQueryVO),InnerWorkShiftModelScheduleDTO.class); } @Override public List<ScheduleShiftCalendarDTO> queryByShiftModelCode(List<String> shiftModelCodeList, Date date) { QueryWrapper<ScheduleShiftCalendar> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().in(CollectionUtil.isNotEmpty(shiftModelCodeList),ScheduleShiftCalendar::getShiftModelCode, shiftModelCodeList) .eq(ObjectUtil.isNotNull(date),ScheduleShiftCalendar::getCalDate, date); List<ScheduleShiftCalendar> list = list(queryWrapper); return BeanUtil.copyToList(list, ScheduleShiftCalendarDTO.class); } @Override public void deleteCalendar(ScheduleTask scheduleTask, String taskVersion, List<String> lineCodeList) { Set<String> stationCode = getStationCodeList(scheduleTask,lineCodeList); scheduleShiftCalendarDao.deleteCalendar(scheduleTask.getTaskCode(), taskVersion, stationCode); } /** * 查询工作中心日历数据(当前获取不到,获取上级数据) * @param dataList 结果数据 * @param versionDataList 日历数据 * @param workCenterList 工作中心集合 * @param currentWorkCenterList 当前层级工作中心集合 */ private void findScheduleShiftCalendarDataList(List<ScheduleShiftCalendarDTO> dataList ,List<ScheduleShiftCalendarDTO> versionDataList ,List<WorkCenterDTO> workCenterList ,List<WorkCenterDTO> currentWorkCenterList ){ List<WorkCenterDTO> hasNoCalendarWorkcenterList = new ArrayList<>(); currentWorkCenterList.forEach(e -> { List<ScheduleShiftCalendarDTO> list = versionDataList.stream() .filter(f -> f.getWorkCenterCode().equals(e.getWorkCenterCode())) .collect(Collectors.toList()); if (!CollectionUtils.isEmpty(list)) { // 系统包含默认数据,再过滤非默认版本数据 list = list.stream().filter(m->BusinessConstants.DB_STR_DEFAULT.equals(m.getTaskVersion())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(list)) { dataList.addAll(list); } } else { hasNoCalendarWorkcenterList.add(e); } }); //获取上级工作中心日历数据 hasNoCalendarWorkcenterList.forEach(e->{ List<ScheduleShiftCalendarDTO> parentScheduleShiftCalendarDataList = findParentScheduleShiftCalendarDataList(e,versionDataList,workCenterList); List<ScheduleShiftCalendarDTO> copyList = BeanUtil.copyToList(parentScheduleShiftCalendarDataList,ScheduleShiftCalendarDTO.class); copyList.forEach(p->{ //父级日历工作中心信息赋值为当前叶子节点工作中心 p.setWorkCenterCode(e.getWorkCenterCode()); p.setWorkCenterName(e.getWorkCenterName()); }); dataList.addAll(copyList); }); } /** * 查询父级工作中心日历数据(当前获取不到,获取上级数据) * @param hasNoCalendarWorkcenter 当前未获取到日历的对象 * @param versionDataList 日历数据 * @param workcenterList 工作中心集合 */ private List<ScheduleShiftCalendarDTO> findParentScheduleShiftCalendarDataList(WorkCenterDTO hasNoCalendarWorkcenter , List<ScheduleShiftCalendarDTO> versionDataList , List<WorkCenterDTO> workcenterList){ Long parentId = hasNoCalendarWorkcenter.getParentId(); WorkCenterDTO parentWorkcenter = workcenterList.stream() .filter(e -> parentId.compareTo(e.getId()) == 0).findFirst().orElse(null); if( parentWorkcenter == null){ // 无上级工作中心 return new ArrayList<>(); } // 上级工作中心日历数据获取 List<ScheduleShiftCalendarDTO> parentScheduleShiftCalendarList = versionDataList.stream() .filter(e -> e.getWorkCenterCode().equals(parentWorkcenter.getWorkCenterCode())) .collect(Collectors.toList()); if(!CollectionUtils.isEmpty(parentScheduleShiftCalendarList) || parentWorkcenter.getParentId()==null){ // 获取到日历返回 或者 已经无上级的情况 return parentScheduleShiftCalendarList; }else{ //未获取到工作日历继续获取上层日历 return findParentScheduleShiftCalendarDataList(parentWorkcenter,versionDataList,workcenterList); } } /** * 组装查询条件包装器。 * * @param vo 查询条件对象,封装了所有的查询参数。 * @return QueryWrapper<ScheduleShiftCalendarDTO> 查询条件包装器,用于Hibernate或MyBatis等框架的查询操作。 */ private QueryWrapper<ScheduleShiftCalendar> assembleQueryWrapper(ScheduleShiftCalendarQueryVO vo) { QueryWrapper<ScheduleShiftCalendar> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(ScheduleShiftCalendar::getDelFlag, BaseModel.DEL_FLAG_NORMAL) .eq(StringUtils.isNotBlank(vo.getWorkCenterCode()), ScheduleShiftCalendar::getWorkCenterCode, vo.getWorkCenterCode()) .eq(StringUtils.isNotBlank(vo.getDefaultFlag()), ScheduleShiftCalendar::getDefaultFlag, vo.getDefaultFlag()) .in(!CollectionUtils.isEmpty(vo.getWorkCenterCodeList()), ScheduleShiftCalendar::getWorkCenterCode, vo.getWorkCenterCodeList()) .eq(ObjectUtil.isNotEmpty(vo.getCalDate()), ScheduleShiftCalendar::getCalDate, vo.getCalDate()) .eq(StringUtils.isNotBlank(vo.getTaskCode()), ScheduleShiftCalendar::getTaskCode, vo.getTaskCode()) .eq(StringUtils.isNotBlank(vo.getTaskVersion()), ScheduleShiftCalendar::getTaskVersion, vo.getTaskVersion()); if(ObjectUtil.isNotEmpty(vo.getStartCalDate()) && (ObjectUtil.isNotEmpty(vo.getEndCalDate()))){ queryWrapper.lambda().between(ScheduleShiftCalendar::getCalDate, vo.getStartCalDate(), vo.getEndCalDate()); } return queryWrapper; } private Set<String> getStationCodeList(ScheduleTask scheduleTask,List<String> sourceCodeList) { //找到总成,精工,压铸所有车间的计划单 List<SchedulingOrder> productOrderList = scheduleGateway.queryScheduleProductOrderList(sourceCodeList, scheduleTask.getWeek()); //计划数量为0,不参与排产 productOrderList = productOrderList.stream().filter(order -> order.getQuantity() > 0).collect(Collectors.toList()); //设备集合 Set<String> scheduleStationCodeSet = new HashSet<>(); //工艺路线 List<org.apache.commons.lang3.tuple.Pair<String, String>> processRoutePairList = Lists.newArrayList(); productOrderList.forEach(scheduleOrder -> processRoutePairList.add(org.apache.commons.lang3.tuple.Pair.of(scheduleOrder.getProcessRouteCode(), scheduleOrder.getProcessRouteVersion()))); List<ProcessRouteDetailsDTO> processRouteList = scheduleGateway.queryProcessRouteListFormMes(processRoutePairList); if (CollectionUtil.isEmpty(processRouteList) ) { throw BusinessException.e(ErrorCode.ERROR, "排程失败,未获取到工艺路线"); } if(processRoutePairList.size() != processRouteList.size()){ throw BusinessException.e(ErrorCode.ERROR, "排程失败,找到的工艺路线不全"); } Map<org.apache.commons.lang3.tuple.Pair<String, String>, ProcessRouteDetailsDTO> processRouteMapping = processRouteList.stream().collect(Collectors.toMap(item -> org.apache.commons.lang3.tuple.Pair.of(item.getProcessRouteCode(), item.getProcessRouteVersion()), Function.identity())); productOrderList.forEach(scheduleOrder -> { //工艺路线 ProcessRouteDetailsDTO processRoute = processRouteMapping.get(org.apache.commons.lang3.tuple.Pair.of(scheduleOrder.getProcessRouteCode(), scheduleOrder.getProcessRouteVersion())); List<OperationDTO> operationDTOList = processRoute.getOperationList(); operationDTOList.forEach(operationDTO -> operationDTO.getStationList().forEach(stationDTO -> scheduleStationCodeSet.add(stationDTO.getCode()))); }); return scheduleStationCodeSet; } @Component protected static class ScheduleShiftCalendarBatchRepositoryImpl extends BatchRepositoryHelperImpl<ScheduleShiftCalendarDao, ScheduleShiftCalendar> { } }
最新发布
09-03
using Blazored.LocalStorage; using DocumentFormat.OpenXml.ExtendedProperties; using DocumentFormat.OpenXml.Math; using log4net; using log4net.Config; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Server.Circuits; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Org.BouncyCastle.Crypto.Engines; using Radzen; using Radzen.Blazor.Rendering; using SqlSugar.IOC; using System.IdentityModel.Tokens.Jwt; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using Tewr.Blazor.FileReader; using WebApi.AgvServer.Api; using WebApi.AgvServer.Auth; using WebApi.AgvServer.Handles; using WebApi.AgvServer.Services; using WebApi.AgvServer.TimerService; using WebApi.AgvServer.Utility; using WebApi.AgvServer.Utility._AutoMapper; using WebApi.Common.Helper; using WebApi.Common.LicenceHelper; using WebApi.Common.Logger; using WebApi.IRepository; using WebApi.IRepository.Agvs; using WebApi.IRepository.Path; using WebApi.IRepository.Stations; using WebApi.IRepository.Tasks; using WebApi.IRepository.Users; using WebApi.IService; using WebApi.IService.AgvCommunication; using WebApi.IService.Agvs; using WebApi.IService.External; using WebApi.IService.Path; using WebApi.IService.Stations; using WebApi.IService.Tasks; using WebApi.IService.Users; using WebApi.Model.Common; using WebApi.Repository; using WebApi.Repository.Agvs; using WebApi.Repository.Path; using WebApi.Repository.Stations; using WebApi.Repository.Tasks; using WebApi.Repository.Users; using WebApi.Service; using WebApi.Service.AgvCommunication; using WebApi.Service.Agvs; using WebApi.Service.External; using WebApi.Service.Path; using WebApi.Service.Stations; using WebApi.Service.Tasks; using WebApi.Service.Users; using System.Net.Http; #region ���ÿ��ٱ༭ģʽ����windowsϵͳ��ע�͵� const int STD_INPUT_HANDLE = -10; const uint ENABLE_QUICK_EDIT_MODE = 0x0040; const uint ENABLE_INSERT_MODE = 0x0020; [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr GetStdHandle(int hConsoleHandle); [DllImport("kernel32.dll", SetLastError = true)] static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint mode); [DllImport("kernel32.dll", SetLastError = true)] static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint mode); #endregion #region ���ÿ��ٱ༭ģʽ����windowsϵͳ��ע�͵� IntPtr hStdin = GetStdHandle(STD_INPUT_HANDLE); uint mode; GetConsoleMode(hStdin, out mode); mode &= ~ENABLE_QUICK_EDIT_MODE;//�Ƴ����ٱ༭ģʽ mode &= ~ENABLE_INSERT_MODE; //�Ƴ�����ģʽ SetConsoleMode(hStdin, mode); #endregion #region �����windowsϵͳ�����ÿ���̨���ڱ��� [DllImport("kernel32.dll", SetLastError = true)] static extern bool SetConsoleTitle(string lpConsoleTitle); // ���ÿ���̨���ڱ��� SetConsoleTitle("AGV���ȹ���ϵͳ"); #endregion var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddHttpContextAccessor(); builder.Configuration.AddJsonFile("appsettings.json"); // 注册 HttpClientFactory builder.Services.AddHttpClient(); #region Swaggerע�� builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi.AgvServer", Version = "v1" }); #region SwaggerGen ��Ȩ��� c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Description = "ֱ��������������Bearer {token}(ע���м��пո�)", Name = "Authorization", BearerFormat = "JWT", Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference= new OpenApiReference { Type=ReferenceType.SecurityScheme, Id="Bearer" } }, new string[]{ } } }); #endregion }); #endregion #region SqlSugar IOC var sqlInfo = builder.Configuration.GetSection(nameof(SQLInfo)).Get<SQLInfo>(); if (sqlInfo != null) { #region �������� //MySql = 0, //SqlServer = 1, //Sqlite = 2, //Oracle = 3, //PostgreSQL = 4, //Dm = 5, //Kdbndp = 6, //Oscar = 7, //MySqlConnector = 8, //Access = 9, //OpenGauss = 10, //QuestDB = 11, //HG = 12, //ClickHouse = 13, //GBase = 14, //Odbc = 15, //OceanBaseForOracle = 16, //TDengine = 17, //GaussDB = 18, //OceanBase = 19, //Tidb = 20, //Vastbase = 21, //PolarDB = 22, //Doris = 23, //Xugu = 24, //GoldenDB = 25, //TDSQLForPGODBC = 26, //TDSQL = 27, //HANA = 28, //DB2 = 29, //GaussDBNative = 30, //DuckDB = 31, //MongoDb = 32, //Custom = 900 #endregion builder.Services.AddSqlSugar(new IocConfig() { ConnectionString = sqlInfo.ConnStr, DbType = sqlInfo.SQLType, IsAutoCloseConnection = true,//�Զ��ͷ� }); #region �������� //services.ConfigurationSugar(db => //{ // db.CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices() // {//�������� // DataInfoCacheService = myCache, // }; // db.CurrentConnectionConfig.MoreSettings = new ConnMoreSettings() // { // IsAutoRemoveDataCache = true // }; //}); #endregion } #endregion #region ��֤ //��֤ע�� builder.Services.AddScoped<ImitateAuthStateProvider>(); builder.Services.AddScoped<AuthenticationStateProvider>(implementationFactory => implementationFactory.GetRequiredService<ImitateAuthStateProvider>()); //jwt builder.Services.AddScoped<JwtSecurityTokenHandler>(); #region httpclientע�� builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://localhost:9000") }); builder.Services.AddScoped<IAuthService, AuthService>(); builder.Services.AddScoped<AuthController>(); builder.Services.AddScoped<agvController>(); builder.Services.AddBlazoredLocalStorage(config => config.JsonSerializerOptions.WriteIndented = true); #endregion //jwt��֤ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { //ȡ��˽Կ var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"] ?? "Blazor!SecKey@okagv@vvip.GANLIHUA2025"); options.TokenValidationParameters = new TokenValidationParameters() { //��֤������ ValidateIssuer = true, ValidIssuer = builder.Configuration["Authentication:Issuer"], //��֤������ ValidateAudience = true, ValidAudience = builder.Configuration["Authentication:Audience"], //��֤�Ƿ���� ValidateLifetime = true, //��֤˽Կ IssuerSigningKey = new SymmetricSecurityKey(secretByte) }; }); //jwt��չ builder.Services.AddScoped<IJWTHelper, JWTHelper>(); #endregion #region ��ȡ��Ŀ���� var projectName = builder.Configuration["Authentication:Audience"]; if (projectName == null) { projectName = "Test"; } #endregion #region Radzenע�� //Radzen builder.Services.AddRadzenComponents(); builder.Services.AddFileReaderService(); builder.Services.AddRadzenCookieThemeService(options => { options.Name = $"{projectName}RadzenBlazorTheme"; // The name of the cookie options.Duration = TimeSpan.FromDays(365); // The duration of the cookie }); //services.AddServerSideBlazor().AddHubOptions(o => //{ // o.MaximumReceiveMessageSize = 64 * 1024; //}); builder.Services.AddScoped<DialogService>(); builder.Services.AddScoped<NotificationService>(); builder.Services.AddScoped<ContextMenuService>(); #endregion #region IOC����ע�� builder.Services.AddCustomIOC(); #endregion #region JWT��Ȩ //builder.Services.AddCustomJWT(); #endregion #region AutoMapper builder.Services.AddAutoMapper(typeof(CustomAutoMapperProfile)); #endregion #region log4net builder.Services.AddControllers().AddControllersAsServices(); Log4netHelper.Repository = LogManager.CreateRepository("NETCoreRepository"); XmlConfigurator.Configure(Log4netHelper.Repository, new System.IO.FileInfo(System.IO.Path.GetDirectoryName(typeof(Program).Assembly.Location) + "/Config/log4net.config")); #endregion #region net logger var verstion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown"; builder.Logging.AddLocalFileLogger(options => { options.SaveDays = 60; options.Verstion = verstion; }); #endregion #region cookie builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme). AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => { o.LoginPath = new PathString("/Home/Login"); }); #endregion #region ��ȡappsetting���� try { //TaskInfo.IsAutoTask = ParamtersSettings.Load().IsAutoTask; //TaskInfo.IsAutoSendToAGV = ParamtersSettings.Load().IsAutoSendToNDC; //TaskInfo.LastKey = ParamtersSettings.Load().NncKey; //TaskInfo.TaskPause = ParamtersSettings.Load().TaskPause; //TaskInfo.SetTaskMode = ParamtersSettings.Load().SetTaskMode; //AGVMapInfo.mapInfo = ParamtersSettings.Load().mapInfo; //if (AGVMapInfo.mapInfo == null) //{ // AGVMapInfo.mapInfo = new AGVMapInfo(); // ParamtersSettings paramters = ParamtersSettings.Load(); // paramters.mapInfo = AGVMapInfo.mapInfo; // paramters.Save(); //} } catch { } #endregion #region ע��Licenceϵͳ��Ϣ�ļ� string computerFile = LicenceHelper.GetComputerInfoAndGenerateFile(); #endregion builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } //app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.MapControllers();//���ӿ��Ʋ����ս�� app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); //app.MapFallbackToPage("/Login"); #region ���ػ��������� //const string CULTURE_CHINESE = "zh-CN"; //const string CULTURE_ENGLISTH = "en-US"; //const string CULTURE_RUSSIA = "ru-RU"; //app.UseRequestLocalization(options => //{ // var cultures = new[] { CULTURE_CHINESE, CULTURE_ENGLISTH, CULTURE_RUSSIA }; // options.AddSupportedCultures(cultures); // options.AddSupportedUICultures(cultures); // options.SetDefaultCulture(CULTURE_ENGLISTH); // // ��Http��Ӧʱ���� ��ǰ������Ϣ ���õ� Response Header��Content-Language �� // options.ApplyCurrentCultureToResponseHeaders = true; //}); #endregion app.UseAuthentication(); app.UseAuthorization(); app.Run(); #region �ⲿIO����ע�� public static class IOCExtend { /// <summary> /// ע���ⲿ���� /// </summary> /// <param name="services"></param> /// <returns></returns> public static IServiceCollection AddCustomIOC(this IServiceCollection services) { #region �Ż�SignalIR�����紫�� services.AddSignalR().AddJsonProtocol(options => { options.PayloadSerializerOptions.WriteIndented = false; // ����JSON��������С������� }); #endregion services.AddSingleton<CircuitHandler, CustomCircuitHandler>(); services.AddSingleton<IUserInfoRepository, UserInfoRepository>(); services.AddSingleton<IRoleInfoRepository, RoleInfoRepository>(); services.AddSingleton<IRightInfoRepository, RightInfoRepository>(); services.AddSingleton<IRoleRightMappingRepository, RoleRightMappingRepository>(); services.AddSingleton<IAgvInfoRepository, AgvInfoRepository>(); services.AddSingleton<IAgvConfigInfoRepository, AgvConfigInfoRepository>(); services.AddSingleton<IAgvErrorInfoRepository, AgvErrorInfoRepository>(); services.AddSingleton<IProcessInfoRepository, ProcessInfoRepository>(); services.AddSingleton<ITaskInfoRepository, TaskInfoRepository>(); services.AddSingleton<IAreaInfoRepository, AreaInfoRepository>(); services.AddSingleton<IStationInfoRepository, StationInfoRepository>(); services.AddSingleton<ILogInfoRepository, LogInfoRepository>(); services.AddSingleton<IControlAreaInfoRepository, ControlAreaInfoRepository>(); services.AddSingleton<IPointInfoRepository, PointInfoRepository>(); services.AddSingleton<ILineInfoRepository, LineInfoRepository>(); services.AddSingleton<IDTCInfoRepository, DTCInfoRepository>(); services.AddSingleton<IStationTypeInfoRespository, StationTypeInfoRepository>(); services.AddSingleton<IStationTypeReleInfoRepository, StationTypeReleInfoRepository>(); services.AddSingleton<ISystemConfigInfoRepository, SystemConfigInfoRepository>(); services.AddSingleton<IUserInfoService, UserInfoService>(); services.AddSingleton<IRoleInfoService, RoleInfoService>(); services.AddSingleton<IRightInfoService, RightInfoService>(); services.AddSingleton<IRoleRightMappingService, RoleRightMappingService>(); services.AddSingleton<IAgvInfoService, AgvInfoService>(); services.AddSingleton<IAgvConfigInfoService, AgvConfigInfoService>(); services.AddSingleton<IAgvErrorInfoService, AgvErrorInfoService>(); services.AddSingleton<IProcessInfoService, ProcessInfoService>(); services.AddSingleton<ITaskInfoService, TaskInfoService>(); services.AddSingleton<IAreaInfoService, AreaInfoService>(); services.AddSingleton<IStationInfoService, StationInfoService>(); services.AddSingleton<ILogInfoService, LogInfoService>(); services.AddSingleton<IModbusService, ModbusService>(); services.AddSingleton<IControlButtonOpenTcpService, ControlButtonOpenTcpService>(); services.AddSingleton<IMqttClientService, MqttClientService>(); services.AddSingleton<INDCService, NDCService>(); services.AddSingleton<IControlAreaInfoService, ControlAreaInfoService>(); services.AddSingleton<IPointInfoService, PointInfoService>(); services.AddSingleton<ILineInfoService, LineInfoService>(); services.AddSingleton<IOpenTcpService, OpenTcpService>(); services.AddSingleton<IDTCInfoService, DTCInfoService>(); services.AddSingleton<IStationTypeInfoService, StationTypeInfoService>(); services.AddSingleton<IStationTypeReleInfoService, StationTypeReleInfoService>(); services.AddSingleton<IStationCommunicationService, StationCommunicationService>(); services.AddSingleton<IWcsHttpService, WcsHttpService>(); services.AddSingleton<ISystemConfigInfoService, SystemConfigService>(); services.AddScoped<NorthwindService>(); //services.AddSingleton<ISplitterCommunicationService, SplitterCommunicationService>(); //TimerService services.AddHostedService<NdcGlobalParameterTimerService>(); services.AddHostedService<TaskIssuedTimerService>(); services.AddHostedService<TaskUpdateToSqlTimerService>(); services.AddHostedService<ProcessUpdateToSqlTimerService>(); services.AddHostedService<CreateTaskTimerService>(); services.AddHostedService<AreaUpdateToSqlTimerService>(); services.AddHostedService<StationUpdateToSqlTimerService>(); services.AddHostedService<TaskLeaveSyncTimerService>(); services.AddHostedService<TaskEnterSyncTimerService>(); services.AddHostedService<OpenTcpTimerService>(); services.AddHostedService<StationCommunicationTimerService>(); services.AddHostedService<AgvRunTimeCalculateTimerService>(); services.AddHostedService<TaskRequestToWMSTimerService>(); services.AddHostedService<NdcLocalModeModbusTimerService>(); services.AddHostedService<DataInitializationTimerService>(); services.AddHostedService<LicenceTimerService>(); // services.AddHostedService<SplitterCommunicationTimerService>(); return services; } public static IServiceCollection AddCustomJWT(this IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SDMC-CJAS1-SAD-DFSFA-SADHJVF-VF")), ValidateIssuer = true, ValidIssuer = "http://localhost:6000", ValidateAudience = true, ValidAudience = "http://localhost:8080", ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(value: 60) }; }); return services; } } #endregion 比如我这个代码要注册后再SplitterCommunicationService中使用该怎么注册
08-15
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值