This commit is contained in:
wanghu
2026-09-02 09:38:45 +08:00
commit 8774b6cc44
128 changed files with 9382 additions and 0 deletions
@@ -0,0 +1,169 @@
// 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;