Files
yunhai.netcore.tool/BasePlatformDotnet/samples/Yh.SchClass.DebugTool/Program.cs
T
2026-09-02 09:38:45 +08:00

170 lines
7.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SchClass OpenAPI 调试入口:独立控制台,不开测试即可联调教务后端。
//
// 用法:
// dotnet run --project samples/Yh.SchClass.DebugTool # 跑全部 20 个端点
// dotnet run --project samples/Yh.SchClass.DebugTool -- --list # 只列出端点名
// dotnet run --project samples/Yh.SchClass.DebugTool -- --only=OAStu
// dotnet run --project samples/Yh.SchClass.DebugTool -- --host=http://192.168.1.20:8080 --path=/bschclass
// 可覆盖项:--host --path --sch --class --tea --group --only
//
// 地址优先级:命令行参数 → 环境变量 YH_SCHCLASS_DEBUG_* → appsettings.json(yh:schclass:open → yh:open)→ 内置默认。
using System.Text;
using Microsoft.Extensions.Configuration;
using Yh.SchClass.OpenApi;
Console.OutputEncoding = Encoding.UTF8;
const string DefaultHost = "http://base.yunhaixingtong.com";
const string DefaultPath = "/bschclass";
string? host = null, path = null, sch = null, classId = null, teaRaw = null, groupRaw = null, only = null;
bool listOnly = false;
// 环境变量兜底(与测试工程的 SchClassLiveDebug 同名同义)
string? Env(string n) { var v = Environment.GetEnvironmentVariable(n); return string.IsNullOrWhiteSpace(v) ? null : v.Trim(); }
host = Env("YH_SCHCLASS_DEBUG_HOST");
path = Env("YH_SCHCLASS_DEBUG_PATH");
sch = Env("YH_SCHCLASS_DEBUG_SCH");
classId = Env("YH_SCHCLASS_DEBUG_CLASS");
teaRaw = Env("YH_SCHCLASS_DEBUG_TEA");
groupRaw = Env("YH_SCHCLASS_DEBUG_GROUP");
// 命令行参数优先
foreach (var arg in args)
{
if (!arg.StartsWith("--")) { continue; }
var kv = arg[2..].Split('=', 2);
var key = kv[0].Trim().ToLowerInvariant();
var val = kv.Length > 1 ? kv[1].Trim() : null;
switch (key)
{
case "host": host = val; break;
case "path": path = val; break;
case "sch": sch = val; break;
case "class": classId = val; break;
case "tea": teaRaw = val; break;
case "group": groupRaw = val; break;
case "only": only = val; break;
case "list": listOnly = true; break;
}
}
var config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.Build();
host ??= config["yh:schclass:open:BaseHost"] ?? config["yh:open:BaseHost"] ?? DefaultHost;
path ??= config["yh:schclass:open:BasePath"] ?? config["yh:open:SchClassPath"] ?? DefaultPath;
var options = new SchClassOpenApiOptions { BaseHost = host, BasePath = string.IsNullOrWhiteSpace(path) ? null : path };
var api = SchClassOpenApiFactory.Create(options);
// ---- 构造调试用例(缺省 ID 一律从真实数据推导,避免捏造 ID 造成假 0 条) ----
var group = int.TryParse(groupRaw, out var g) ? g : 3;
var teaId = int.TryParse(teaRaw, out var t) ? t : 0;
Console.WriteLine($"目标:{options.ResolveBaseUrl()}");
// --list:只打印端点名,不做任何网络请求
if (listOnly)
{
foreach (var name in new[]
{
"DbClass.GetSchteaList", "VSchClass.GetVClassList", "VSchClass.GetSchArrVClassListAll",
"VSchClass.GetSchArrVClassListPost", "Schoolen.GetSchLenLevellist", "Schoolen.GetSchLenlist",
"UserInfo.GetUserList", "SchInfo.AllList", "SchInfo.GetSchlist", "OATea.GetSchTeainfo",
"OATea.GetArrTeainfo", "OAStu.GetAllStulist", "OAStu.GetSchStulist", "OAStu.GetClaStulist",
"TeachInfo.GetSchTeachlist", "TeachInfo.GetSchClaTeachlist", "SubInfo.GetSchTeachSublist",
"SubInfo.GetSchSublist", "FamCom.GetStuUserFamIDList", "FamCom.GetAllStuFamMem",
})
{
Console.WriteLine(name);
}
return 0;
}
var schResolved = sch;
var cases = new List<(string Name, Func<Task<int>> Call)>();
// 先探测学校列表,推导缺省参数
try
{
var schools = await api.SchInfo.AllListAsync();
Console.WriteLine($"学校列表:{schools.Count} 所(前 3:{string.Join(" | ", schools.Take(3).Select(s => $"{s.SchName}[{s.SchSerId}]"))})");
schResolved ??= schools.FirstOrDefault()?.SchSerId ?? "S001";
}
catch (Exception e)
{
Console.WriteLine($"!! 学校列表探测失败:{e.GetType().Name}: {e.Message}");
Console.WriteLine("后端不可达时后续端点大概率全部失败,仍继续逐个执行以便核对。");
schResolved ??= "S001";
}
if (!listOnly)
{
var sch2 = schResolved;
string cid = classId ?? "";
if (cid.Length == 0)
{
var cls = (await api.VClass.GetVClassListAsync(sch2)).FirstOrDefault();
cid = cls != null && cls.TryGetValue("ClassID", out var c) ? c.ToString() ?? "1001" : "1001";
}
if (teaId == 0)
{
var tea = (await api.DbClass.GetSchteaListAsync(group)).FirstOrDefault();
teaId = tea != null && tea.TryGetValue("UserTeaSerID", out var d) && int.TryParse(d.ToString(), out var p) ? p : 77;
}
Console.WriteLine($"参数:sch={sch2} classId={cid} teaId={teaId} group={group}");
cases.Add(("DbClass.GetSchteaList", async () => (await api.DbClass.GetSchteaListAsync(group)).Count));
cases.Add(("VSchClass.GetVClassList", async () => (await api.VClass.GetVClassListAsync(sch2)).Count));
cases.Add(("VSchClass.GetSchArrVClassListAll", async () => (await api.VClass.GetSchArrVClassListAllAsync()).Count));
cases.Add(("VSchClass.GetSchArrVClassListPost", async () => (await api.VClass.GetSchArrVClassListPostAsync(sch2)).Count));
cases.Add(("Schoolen.GetSchLenLevellist", async () => (await api.Schooling.GetSchLenLevelListAsync(sch2)).Count));
cases.Add(("Schoolen.GetSchLenlist", async () => (await api.Schooling.GetSchLenListAsync(sch2)).Count));
cases.Add(("UserInfo.GetUserList", async () => (await api.UserInfo.GetUserListAsync(sch2)).Count));
cases.Add(("SchInfo.AllList", async () => (await api.SchInfo.AllListAsync()).Count));
cases.Add(("SchInfo.GetSchlist", async () => (await api.SchInfo.GetSchListAsync(null)).Count));
cases.Add(("OATea.GetSchTeainfo", async () => (await api.TeaInfo.GetSchTeaInfoAsync(sch2, null)).Count));
cases.Add(("OATea.GetArrTeainfo", async () => (await api.TeaInfo.GetArrTeaInfoAsync(teaId.ToString())).Count));
cases.Add(("OAStu.GetAllStulist", async () => (await api.StuInfo.GetAllStuListAsync()).Count));
cases.Add(("OAStu.GetSchStulist", async () => (await api.StuInfo.GetSchStuListAsync(sch2, null)).Count));
cases.Add(("OAStu.GetClaStulist", async () => (await api.StuInfo.GetClaStuListAsync(cid, null)).Count));
cases.Add(("TeachInfo.GetSchTeachlist", async () => (await api.TeachInfo.GetSchTeachListAsync(sch2, teaId)).Count));
cases.Add(("TeachInfo.GetSchClaTeachlist", async () => (await api.TeachInfo.GetSchClaTeachListAsync(cid)).Count));
cases.Add(("SubInfo.GetSchTeachSublist", async () => (await api.SubInfo.GetSchTeachSubListAsync(sch2)).Count));
cases.Add(("SubInfo.GetSchSublist", async () => (await api.SubInfo.GetSchSubListAsync(sch2, null, null)).Count));
cases.Add(("FamCom.GetStuUserFamIDList", async () => (await api.FamilyCompat.GetStuUserFamIdListAsync("1,2")).Count));
cases.Add(("FamCom.GetAllStuFamMem", async () => (await api.FamilyCompat.GetAllStuFamMemAsync("1,2")).Count));
}
var failures = new List<string>();
if (only != null)
{
cases = cases.Where(c => c.Name.Contains(only, StringComparison.OrdinalIgnoreCase)).ToList();
if (cases.Count == 0)
{
Console.WriteLine($"--only={only} 未匹配任何端点(用 --list 查看全部名称)");
return 2;
}
}
foreach (var (name, call) in cases)
{
try
{
var count = await call();
Console.WriteLine($" OK {name} -> {count} 条");
}
catch (Exception e)
{
failures.Add(name);
Console.WriteLine($" FAIL {name} -> {e.GetType().Name}: {e.Message}");
}
}
Console.WriteLine($"汇总:{cases.Count - failures.Count}/{cases.Count} 通过");
return failures.Count == 0 ? 0 : 1;