tasks.md 7.9 KB

1. 新建 C# 项目骨架(DRGInterfaceClient/)

  • 1.1 创建 DRGInterfaceClient/DRGInterfaceClient.csproj:<OutputType>WinExe</OutputType>、<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>、<ProjectTypeGuids>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>、<RootNamespace>DRG.DRGInterfaceClient</RootNamespace>;引用 System、System.Windows.Forms、System.Net.Http、System.Web.Extensions、System.Drawing、System.Xml。不引入任何第三方 NuGet 包。
  • 1.2 创建 DRGInterfaceClient/Program.cs:入口;若命令行含 --sync → 进入 HeadlessRunner.RunOnceAsync() 后 Environment.Exit(code);否则启动 WinForms Application.Run(new MainForm())(含托盘 NotifyIcon)。
  • 1.3 创建 DRGInterfaceClient/appsettings.json:字段 Endpoint(默认 http://127.0.0.1:52773/csp/drg/sysInternalMutiple)、AuthToken(默认 X1NZU1RFTTpwcnlrQDIwMjA=)、ScheduledHospCode(默认空)、TaskName(默认 DRGInterfaceClientSync)、MaxLogSizeMB(默认 5)、FullSyncStartDays(默认 365)、SessionDefaults(默认 userID="DRGClient"、userName="接口客户端"、其余空字符串);设为复制输出目录。
  • 1.4 创建 DRGInterfaceClient/Config.cs:反序列化 appsettings.json(JavaScriptSerializer),提供 Config.Current 单例;定义 AppConfig、SessionDefaults、HospitalInfoItem(id/hospCode/code/descripts/MedinsLv)、SyncConfig(syncType/frequency/scheduledTime/lookbackDays/enabled/synFlag/warningFlag/status) 等模型类。

2. 接口客户端与 Session 构建(DRGInterfaceClient/)

  • 2.1 创建 DRGInterfaceClient/DrgApiClient.cs:沿用既有 HTTP 调用与 JSON 序列化成熟模式(HttpClient + JavaScriptSerializer)。CallAsync(code, paramsObj, session) 组装 {code, params:[{}], session:[{}]},POST Endpoint,带 Authorization: Basic <AuthToken> + Content-Type: application/json;记录 HTTP 状态码/耗时/响应摘要到日志;返回 Dictionary<string,object>。提供 IsOk/GetError/GetResult/GetResultArray/Summarize 辅助。
  • 2.2 实现接口方法:QueryHospitalInfoAsync(active, descripts, session)(01010064)、GetSyncConfigAsync(hospCode, session)(02010079,带 session)、GetInpatientDataAsync(hospCode, stDate, endDate, synFlag, session)(02010067,带 session,参数含 admID='')。
  • 2.3 创建 DRGInterfaceClient/SessionBuilder.cs:Build(HospitalInfoItem hosp, SessionDefaults defaults) → 返回完整 session 字典:hospYBCode=hosp.code、hospCode=hosp.hospCode、hospDesc=hosp.descripts、hospID=hosp.id、medinsLv=hosp.MedinsLv,其余字段取 defaults;非机构字段缺失时填空字符串。BuildDefault 用于首次加载机构的空 session。
  • 2.4 实现机构必填校验:在 GetSyncConfigAsync/GetInpatientDataAsync 调用前(MainForm.EnsureHospital()),若未选中机构 → 弹"请先选择医疗机构"提示且不发起 HTTP(DrgApiClient 始终带 session,机构字段由 session 强制填充)。

3. 本地滚动日志(DRGInterfaceClient/)

  • 3.1 创建 DRGInterfaceClient/Logger.cs:静态 Info/Warn/Error(msg, ex?),写 DRGInterfaceClient.log(程序目录),格式 [yyyy-MM-dd HH:mm:ss.fff] [LEVEL] [CODE] msg;超过 MaxLogSizeMB 时滚动为 .log.1;提供 ReadAll() 供界面展示、OpenLogFile()(Process.Start)、Clear()。
  • 3.2 主界面日志面板绑定:MainForm 内嵌 TextBox(只读、多行) 通过 Logger.OnLog 事件实时追加日志(自动跨线程 Invoke)。

4. 主界面与托盘(DRGInterfaceClient/)

  • 4.1 创建 DRGInterfaceClient/MainForm.cs(WinForms):顶部含「接口地址」TextBox(初始值取自 Config.Current.Endpoint)、机构 ComboBox、「加载机构」「加载配置」「立即执行一次」「开始调度」「停止调度」「注册任务计划」「设为定时机构」「打开日志」「清空日志」按钮、配置展示 Label 组、日志 TextBox。
  • 4.2 接口地址非空校验 EnsureEndpoint():每次调用 01010064/02010079/02010067 前调用;文本框为空 → MessageBox.Show("接口地址不能为空") 并中断(不发起 HTTP);非空 → Config.Current.Endpoint = 文本框值 后继续。启动加载机构:进入界面自动调 QueryHospitalInfoAsync 填充下拉(同样先经 EnsureEndpoint);空结果禁用后续按钮并提示。
  • 4.3 选机构→加载配置:选变更后点「加载配置」→ GetSyncConfigAsync(hospCode)(带 session)→ 展示配置;记录所构建 session。
  • 4.4 立即执行一次:点「立即执行一次」→ 校验已选机构 → 按 02010079 配置计算 stDate/endDate → GetInpatientDataAsync → 写日志;失败弹错误。
  • 4.5 创建 DRGInterfaceClient/TrayIcon.cs:NotifyIcon + ContextMenuStrip(打开主界面/立即执行一次/打开日志/退出);主界面 FormClosing 收起托盘而非退出;双击还原;托盘 ToolTip 显示提示。
  • 4.6 创建 DRGInterfaceClient/SchedulerService.cs:根据 02010079 配置管理调度。「开始调度」按 frequency 分支:hourly→启动内部 System.Timers.Timer(每分钟检查,命中整点 nowMM==0 且距上次执行>55分钟时触发)执行一次 02010067;daily/weekly→调用 4.7 的 schtasks 注册;manual→仅提示不启用。「停止调度」对应停止(hourly 停 Timer / daily|weekly schtasks /Delete)。
  • 4.7 「注册/注销任务计划」(daily/weekly 用):基于 02010079 的 frequency+scheduledTime,用 Process.Start("schtasks", ...) 创建/更新 TaskName 计划任务,操作 "<程序目录>\DRGInterfaceClient.exe" --sync;daily→/SC DAILY /ST HH:mm、weekly→/SC WEEKLY /D MON /ST HH:mm;hourly/manual 不注册(hourly 由 4.6 内部轮询承担)。封装于 TaskSchedulerHelper.cs。
  • 4.8 「设为定时机构」:将当前选中机构的 code(医保机构编码) 写入 appsettings.json 的 ScheduledHospCode 并持久化(Config.Save()),供 --sync 按 code 匹配使用。

5. 无头 --sync 模式(DRGInterfaceClient/)

  • 5.1 创建 DRGInterfaceClient/HeadlessRunner.cs:RunOnceAsync():读 ScheduledHospCode → QueryHospitalInfoAsync 按 code(医保机构编码) 匹配机构 → SessionBuilder.Build → GetSyncConfigAsync → 计算日期 → GetInpatientDataAsync → 日志;成功返回 0、失败/缺失机构返回 1。全程不弹 UI。
  • 5.2 日期计算工具:DrgApiClient.ComputeDateRange(syncType, lookbackDays, fullSyncStartDays) → (stDate, endDate)(格式 yyyy-MM-dd):增量 endDate=今天、stDate=今天-LookbackDays;全量 endDate=今天、stDate=今天-FullSyncStartDays(<=0 则空)。

6. 验证与文档

  • 6.6 编写 DRGInterfaceClient/README.md:说明功能、运行方式(GUI/--sync)、appsettings 配置项、schtasks 注册逻辑、日志位置。
  • 6.1 本地编译 DRGInterfaceClient(VS / msbuild),确认无第三方包依赖、无编译错误。(需在可编译环境执行,本机 shell 受限未能跑)
  • 6.2 运行 GUI:加载机构下拉→选机构→加载配置→查看 session 机构字段映射正确→点「立即执行一次」→ 日志中出现 02010067 成功记录与 session 摘要。
  • 6.3 校验必填:未选机构点按钮 → 提示"请先选择医疗机构",无 HTTP 调用(可用 Fiddler/日志佐证)。
  • 6.4 --sync 验证:设 ScheduledHospCode 后命令行 DRGInterfaceClient.exe --sync → 退出码 0,日志完整;故意清空 ScheduledHospCode → 退出码 1 且日志报错。
  • 6.5 「注册任务计划」验证:配置 daily 02:30 → 运行后 schtasks /Query /TN DRGInterfaceClientSync 可见每日 02:30 触发、操作为 --sync;manual 不注册。