ShouldRunNow 的 hourly 分支跨天去重 bug:删去基于"一天内秒数"的比较(原第 468/470/473 行),改为直接比较完整 $h 时间戳 if pNowH '= pLastRunH { set shouldRun = 1 },进入条件仍为 nowMM=0。daily/weekly 分支增加 ±2 分钟容错窗口:将 quit:(+pNowMM)'=schedMM shouldRun 改为 quit:($zabs(+pNowMM - schedMM) > 2) shouldRun,避免整点抖动漏跑。RunScheduledTasks 中的诊断日志硬编码:将第 335 行 set debugOn = 1 改为 set debugOn = $g(^DRG.HIS.SyncConfig.DebugOn, 0),使生产默认不写 ^DRG.HIS.SyncConfig.Debug。SyncTaskService.cls 到 IRIS(采用既有 scripts/compile_*.cls.sql 或 ##class(...).%Compile() 流程),验证 w ##class(src.DRG.HISData.SyncTaskService).RunNow(1) 能按 hourly 配置正确执行一次、且连续两次调用第二次被去重。HISAutoSyncService/HISAutoSyncService.csproj:<OutputType>Exe</OutputType>、<TargetFramework>net48</TargetFramework>(已确认用 .NET Framework 4.8,系统自带免安装);引用 System.Windows.Forms、System.ServiceProcess、System.Net.Http(均框架自带,无第三方 NuGet 包)。appsettings.json:字段 Endpoint(默认 http://127.0.0.1:52773/csp/drg/sysInternalMutiple)、IntervalSeconds(默认 60)、AuthToken(默认 X1NZU1RFTTpwcnlrQDIwMjA=)、Code(默认 02010083);发布时设为不复制/始终复制均可。SchedulerClient.cs:HttpClient POST Endpoint,Body {"code":"02010083","params":[{}]},Header Authorization: Basic <AuthToken>、Content-Type: application/json;记录每次调用的 HTTP 状态码、耗时(ms)、返回摘要(前 200 字);异常时记录异常信息。AutoSyncService.cs:继承 System.ServiceProcess.ServiceBase;OnStart 启动 System.Timers.Timer(Interval = IntervalSeconds*1000),Elapsed 异步调用 SchedulerClient.TriggerAsync();OnStop 停止定时器。TrayIcon.cs(WinForms NotifyIcon):右键菜单含「立即执行一次」「启动/停止」「打开日志文件」「退出」;气泡/菜单显示上次运行时间与下一次倒计时;仅在交互会话(Environment.UserInteractive 且未带 --service)时启动。Program.cs:参数为 --service 或运行在非交互会话时进入 ServiceBase.Run(new AutoSyncService());否则启动托盘(Application.Run)。进程内统一维护"上次运行时间/下一次时间"状态供托盘展示。HISAutoSyncService.log(与 exe 同目录),按大小或日期滚动,含时间戳、级别、消息;托盘「打开日志」调用 Process.Start 打开该文件。dotnet publish -c Release -r win-x64 --self-contained false,或按 Open Question 1 调整运行时),产物放入部署目录。后端数据库结构开发/IRIS部署脚本/Invoke-HisSyncScheduler.ps1:URL 改为 http://127.0.0.1:52773/csp/drg/sysInternalMutiple;Body 改为 {"code":"02010083","params":[{}]};增加 Authorization 头 Basic X1NZU1RFTTpwcnlrQDIwMjA= 与 Content-Type: application/json;增加 try/catch 与调用结果/错误写入本地日志文件。Register-TaskScheduler.ps1:用 schtasks /Create /SC MINUTE /MO 1 /TN "DRGHISAutoSyncPS" /TR "powershell -ExecutionPolicy Bypass -File '<部署目录>\Invoke-HisSyncScheduler.ps1'" 注册每分钟计划任务;提供 /U 凭据占位说明(建议用 SYSTEM 或专用服务账户)。Install-Service.bat:sc create "DRGHISAutoSync" binPath= "%~dp0HISAutoSyncService.exe --service" start= auto DisplayName= "DRG HIS 自动同步服务",并 sc failure DRGHISAutoSync reset= 0 actions= restart/60000/restart/60000/restart/60000;随后 sc start DRGHISAutoSync。Uninstall-Service.bat:sc stop DRGHISAutoSync 后 sc delete DRGHISAutoSync;并给出移除计划任务的 schtasks /Delete /TN "DRGHISAutoSyncPS" /F 说明。后端数据库结构开发/IRIS部署脚本/ 或 接口服务说明/):说明两种触发器形态、去重安全机制、安装/卸载步骤、日志位置、常见问题排查(如 401 鉴权失败、IRIS 端点不通)。BS_HISSyncConfig 设为 Enabled=1、Frequency=hourly、SyncType=incremental、LookbackDays=3,通过 SyncTaskConfig.tsx 或 SQL 完成。Invoke-HisSyncScheduler.ps1 → 确认 BS_HISSyncConfig.Status 变为 running→success、且 BS_HISSyncLog(02010077 日志)出现一条 TaskName 含"HIS"的同步记录;间隔几分钟后第二次运行确认 executedCount=0(去重生效)。HISAutoSyncService.log 每分钟一次调用、整点触发同步;同时保留计划任务,确认两者并发不重复执行。本会话在本机仓库完成代码与脚本落地(tasks 0.1–0.3、1.1–1.8、2.1–2.4、3.1)。下面 4 项需在 IRIS 服务器与生产机器上执行,已在
后端数据库结构开发/IRIS部署脚本/Readme-HISAutoSync-Deployment.md第 3 节提供完整命令清单:
Do $System.OBJ.Compile("src.DRG.HISData.SyncTaskService","ck"),并用 RunScheduledTasks({}) 验证 hourly 跨天去重生效。BS_HISSyncConfig 启用记录(Frequency=hourly)。Invoke-HisSyncScheduler.ps1,观察 BS_HISSyncConfig.Status 与 BS_HISSyncLog(02010077)。Install-Service.bat 启动 C# 服务,与计划任务并发运行 24 小时,观察 HISAutoSyncService.log 与 BS_HISSyncLog 确认无重复执行。src/src/DRG/HISData/Tests/SyncTaskServiceTest.cls(继承 %UnitTest.TestCase),覆盖:
ShouldRunNow 18 个用例:hourly(首次/同 $h/不同 $h/跨天修复/非整点)、daily(精确/同日期/±2 分钟容错/错小时/空 ScheduledTime)、weekly(非周一/周一精确跨周/同日同时)、未知频率;RunScheduledTasks 2 个集成用例:无启用配置 / 仅 manual 配置;UpdateConfigStatus 2 个健壮性用例:不存在 ID 不崩溃。[ ] 4.2 在 IRIS 终端编译并运行:
Do $System.OBJ.Compile("src.DRG.HISData.Tests.SyncTaskServiceTest","ck")
Do ##class(%UnitTest.Manager).RunTest("src.DRG.HISData.Tests")
全部 22 个用例应 PASS;尤其 TestShouldRunNow_Hourly_CrossDaySameTimeExecutes 与 TestShouldRunNow_Daily_WithinTwoMinuteTolerance 验证本次修复的两个核心点。