using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
namespace DRG.DRGInterfaceClient
{
/// DRG 平台接口 HTTP 客户端(复用 HISAutoSyncService/ConfigApiClient 模式)。
internal static class DrgApiClient
{
// 单天数据量较大时 02010067 可能较慢,超时放宽到 300 秒
private static readonly HttpClient _http = new HttpClient { Timeout = TimeSpan.FromSeconds(300) };
private static readonly JavaScriptSerializer _json = new JavaScriptSerializer();
// ===== 通用调用(所有调用均带 session) =====
public static async Task> CallAsync(
string code, object paramObj, Dictionary session)
{
AppConfig cfg = Config.Current;
var payload = new Dictionary
{
{ "code", code },
{ "params", new[] { paramObj } },
{ "session", new[] { session ?? new Dictionary() } }
};
string json = _json.Serialize(payload);
var req = new HttpRequestMessage(HttpMethod.Post, cfg.Endpoint);
req.Content = new StringContent(json, Encoding.UTF8, "application/json");
req.Headers.TryAddWithoutValidation("Authorization", "Basic " + cfg.AuthToken);
var sw = Stopwatch.StartNew();
try
{
var resp = await _http.SendAsync(req).ConfigureAwait(false);
var text = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
sw.Stop();
Logger.Info(string.Format("[{0}] 请求: {1}", code, json));
Logger.Info(string.Format("[{0}] HTTP {1} 耗时{2}ms 响应: {3}",
code, (int)resp.StatusCode, sw.ElapsedMilliseconds, text));
try { return _json.Deserialize>(text); }
catch (Exception ex)
{
Logger.Error("解析响应失败:" + code, ex);
return ErrorDict(ex);
}
}
catch (Exception ex)
{
sw.Stop();
Logger.Error(string.Format("调用异常 [{0}] 耗时{1}ms", code, sw.ElapsedMilliseconds), ex);
return ErrorDict(ex);
}
}
// ===== 业务接口 =====
public static Task> QueryHospitalInfoAsync(
string active, string descripts, Dictionary session)
{
return CallAsync("01010064", new { active = active ?? "", descripts = descripts ?? "" }, session);
}
public static Task> GetSyncConfigAsync(
string hospCode, Dictionary session)
{
return CallAsync("02010079", new { hospCode }, session);
}
public static Task> GetInpatientDataAsync(
string hospCode, string stDate, string endDate, string synFlag, Dictionary session)
{
return CallAsync("02010067",
new { admID = "", hospID = hospCode, stDate, endDate, SynFlag = synFlag }, session);
}
// ===== 响应解析辅助 =====
public static bool IsOk(Dictionary resp)
{
if (resp == null) return false;
return resp.TryGetValue("errorCode", out object ec)
&& ec != null && ec.ToString() == "0";
}
public static string GetError(Dictionary resp)
{
if (resp == null) return "响应为空";
var msg = resp.TryGetValue("errorMessage", out object m) ? (m ?? "").ToString() : "";
var ec = resp.TryGetValue("errorCode", out object e) ? (e ?? "").ToString() : "";
return string.IsNullOrEmpty(msg) ? ("errorCode=" + ec) : msg;
}
public static Dictionary GetResult(Dictionary resp)
{
if (resp == null) return null;
if (resp.TryGetValue("result", out object r) && r is Dictionary dict) return dict;
return null;
}
public static object[] GetResultArray(Dictionary resp)
{
if (resp == null) return null;
if (resp.TryGetValue("result", out object r))
{
if (r is object[] arr) return arr;
if (r is System.Collections.ArrayList list)
return (object[])list.ToArray(typeof(object));
}
return null;
}
// ===== 模型解析 =====
public static HospitalInfoItem ParseHospital(Dictionary d)
{
if (d == null) return new HospitalInfoItem();
return new HospitalInfoItem
{
id = GetStr(d, "id"),
hospCode = GetStr(d, "hospCode"),
code = GetStr(d, "code"),
descripts = GetStr(d, "descripts"),
MedinsLv = GetStr(d, "MedinsLv")
};
}
public static SyncConfig ParseSyncConfig(Dictionary r)
{
if (r == null) return null;
return new SyncConfig
{
syncType = GetStr(r, "syncType"),
frequency = GetStr(r, "frequency"),
scheduledTime = GetStr(r, "scheduledTime"),
lookbackDays = GetInt(r, "lookbackDays", 3),
enabled = GetBool(r, "enabled", false),
synFlag = GetStr(r, "synFlag", "Y"),
warningFlag = GetStr(r, "warningFlag", "Y"),
status = GetStr(r, "status"),
errorMessage = GetStr(r, "errorMessage")
};
}
/// 根据 syncType 与 lookbackDays 计算 02010067 的日期区间(yyyy-MM-dd)。
public static (string stDate, string endDate) ComputeDateRange(
string syncType, int lookbackDays, int fullSyncStartDays)
{
string today = DateTime.Now.ToString("yyyy-MM-dd");
if (syncType == "full")
{
string st = fullSyncStartDays > 0
? DateTime.Now.AddDays(-fullSyncStartDays).ToString("yyyy-MM-dd")
: "";
return (st, today);
}
int lb = lookbackDays > 0 ? lookbackDays : 3;
return (DateTime.Now.AddDays(-lb).ToString("yyyy-MM-dd"), today);
}
// ===== 按天分批 =====
///
/// 按天拆分日期区间:结束日期晚于开始日期(跨度>1 天)时,拆成每天一段(Item1=Item2=当天);
/// 否则(同一天、开始日期为空或日期非法)返回原区间单段,保持原有一次性调用行为。
/// 目的:避免一次性请求过大区间导致 02010067 接口服务超时。
///
public static List> SplitByDay(string stDate, string endDate)
{
var list = new List>();
DateTime st, ed;
if (string.IsNullOrWhiteSpace(stDate)
|| !DateTime.TryParse(stDate, out st)
|| !DateTime.TryParse(endDate, out ed)
|| ed.Date <= st.Date)
{
list.Add(Tuple.Create(stDate, endDate));
return list;
}
for (DateTime d = st.Date; d <= ed.Date; d = d.AddDays(1))
{
string day = d.ToString("yyyy-MM-dd");
list.Add(Tuple.Create(day, day));
}
return list;
}
// ===== 内部工具 =====
public static string GetStr(Dictionary d, string k, string def = "")
{
if (d.TryGetValue(k, out object v) && v != null) return v.ToString();
return def;
}
public static int GetInt(Dictionary d, string k, int def)
{
if (d.TryGetValue(k, out object v) && v != null)
{
if (v is int i) return i;
if (v is long l) return (int)l;
if (int.TryParse(v.ToString(), out int r)) return r;
}
return def;
}
public static bool GetBool(Dictionary d, string k, bool def)
{
if (d.TryGetValue(k, out object v) && v != null)
{
var s = v.ToString();
if (s == "1" || string.Equals(s, "true", StringComparison.OrdinalIgnoreCase)
|| string.Equals(s, "Y", StringComparison.OrdinalIgnoreCase)) return true;
if (s == "0" || string.Equals(s, "false", StringComparison.OrdinalIgnoreCase)
|| string.Equals(s, "N", StringComparison.OrdinalIgnoreCase)) return false;
}
return def;
}
private static Dictionary ErrorDict(Exception ex)
{
return new Dictionary
{
{ "errorCode", "-1" },
{ "errorMessage", "异常: " + ex.Message }
};
}
}
}