PaperController.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. using Azure.Cosmos;
  2. using Azure.Storage.Blobs;
  3. using Azure.Storage.Blobs.Models;
  4. using Azure.Storage.Sas;
  5. using DocumentFormat.OpenXml.Drawing.Diagrams;
  6. using Microsoft.AspNetCore.Http;
  7. using Microsoft.AspNetCore.Mvc;
  8. using Microsoft.Extensions.Options;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Globalization;
  12. using System.IO;
  13. using System.Text;
  14. using System.Text.Json;
  15. using System.Threading.Tasks;
  16. using TEAMModelBI.Models;
  17. using TEAMModelBI.Tool;
  18. using TEAMModelOS.Models;
  19. using TEAMModelOS.SDK.Context.BI;
  20. using TEAMModelOS.SDK.Context.Constant;
  21. using TEAMModelOS.SDK.DI;
  22. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  23. using TEAMModelOS.SDK.Extension;
  24. using TEAMModelOS.SDK.Models;
  25. using TEAMModelOS.SDK.Models.Cosmos.BI;
  26. namespace TEAMModelBI.Controllers.Census
  27. {
  28. /// <summary>
  29. /// 试卷
  30. /// </summary>
  31. [Route("paper")]
  32. [ApiController]
  33. public class PaperController : ControllerBase
  34. {
  35. private readonly AzureCosmosFactory _azureCosmos;
  36. private readonly AzureStorageFactory _azureStorage;
  37. private readonly DingDing _dingDing;
  38. private readonly Option _option;
  39. public PaperController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option)
  40. {
  41. _azureCosmos = azureCosmos;
  42. _azureStorage = azureStorage;
  43. _dingDing = dingDing;
  44. _option = option?.Value;
  45. }
  46. /// <summary>
  47. /// 查询学校试卷列表
  48. /// </summary>
  49. /// <param name="jsonElement"></param>
  50. /// <returns></returns>
  51. [ProducesDefaultResponseType]
  52. [HttpPost("get-list")]
  53. public async Task<IActionResult> GetList(JsonElement jsonElement)
  54. {
  55. if (!jsonElement.TryGetProperty("code", out JsonElement code)) return BadRequest();
  56. jsonElement.TryGetProperty("scope", out JsonElement _scope);
  57. Dictionary<string, object> dic = new();
  58. if (jsonElement.TryGetProperty("periodId", out JsonElement periodId))
  59. dic.Add("periodId", periodId);
  60. if (jsonElement.TryGetProperty("subjectId", out JsonElement subjectId))
  61. dic.Add("subjectId", subjectId);
  62. if (jsonElement.TryGetProperty("gradeIds", out JsonElement gradeIds))
  63. dic.Add("gradeIds", gradeIds);
  64. if (jsonElement.TryGetProperty("isSort", out JsonElement isSort))
  65. {
  66. if (!string.IsNullOrEmpty($"{isSort}"))
  67. {
  68. if (bool.Parse($"{isSort}") == true)
  69. dic.Add("@DESC", "createTime");
  70. else
  71. dic.Add("@ASC", "createTime");
  72. }
  73. else
  74. dic.Add("@ASC", "createTime");
  75. }
  76. string scope = "school";
  77. if (string.IsNullOrEmpty($"{_scope}"))
  78. scope = $"{_scope}";
  79. var cosmosClinet = _azureCosmos.GetCosmosClient();
  80. StringBuilder sql = new("select value(c) from c ");
  81. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dic, sql);
  82. List<Paper> papers = new();
  83. if (scope.ToString().Equals("school"))
  84. {
  85. await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
  86. {
  87. papers.Add(item);
  88. }
  89. }
  90. return Ok(new { state = RespondCode.Ok,cnt = papers.Count, papers });
  91. }
  92. /// <summary>
  93. /// 复制试卷信息到另外一个学校
  94. /// </summary>
  95. /// <param name="jsonElement"></param>
  96. /// <returns></returns>
  97. [ProducesDefaultResponseType]
  98. [HttpPost("copy-infos")]
  99. public async Task<IActionResult> CopyInfos(JsonElement jsonElement)
  100. {
  101. if (!jsonElement.TryGetProperty("papers", out JsonElement jsPapers)) return BadRequest();
  102. List<CopyPaper> papers = jsPapers.ToObject<List<CopyPaper>>();
  103. var cosmosClinet = _azureCosmos.GetCosmosClient();
  104. foreach (var cItem in papers)
  105. {
  106. Paper paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Paper>(cItem.oldId, new PartitionKey($"Paper-{cItem.oldSc}"));
  107. paper.periodId = cItem.newPrdId;
  108. paper.subjectId = cItem.newSubId;
  109. paper.subjectName = cItem.newSubName;
  110. paper.gradeIds = cItem.newGrId;
  111. paper.code = $"Paper-{cItem.newSc}";
  112. var resState = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(paper.id, new PartitionKey(paper.code));
  113. if (resState.Status == 200)
  114. {
  115. paper.id = Guid.NewGuid().ToString();
  116. }
  117. //paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<Paper>(paper, new PartitionKey(paper.code));
  118. var oldBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.oldSc}");
  119. var newBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.newSc}");
  120. string blobUrl = "";
  121. if (paper.blob.IndexOf('/') == 0)
  122. blobUrl = $"{paper.blob}".Substring(1, paper.blob.Length - 1);
  123. else
  124. blobUrl = $"{paper.blob}";
  125. List<Task<CopyFromUriOperation>> filelist = new(); //可复制256M以上文件
  126. await foreach (BlobItem blobItem in oldBobCilent.GetBlobsAsync(BlobTraits.None, BlobStates.None, blobUrl))
  127. {
  128. if (blobItem.Name.EndsWith(".json"))
  129. {
  130. BlobClient tempClient = oldBobCilent.GetBlobClient(blobItem.Name);
  131. using (var meomoryStream = new MemoryStream())
  132. {
  133. StringBuilder itemStr = new();
  134. BlobClient tempBlobClient = oldBobCilent.GetBlobClient(blobItem.Name);
  135. BlobDownloadInfo download = tempBlobClient.Download();
  136. var content = download.Content;
  137. string text;
  138. using (var streamReader = new StreamReader(content))
  139. {
  140. while ((text = streamReader.ReadLine()) != null)
  141. {
  142. if (streamReader.EndOfStream)
  143. itemStr.Append($"{text.ToString()}");
  144. else
  145. itemStr.Append($"{text.ToString()},");
  146. }
  147. streamReader.Close();
  148. }
  149. string input = itemStr.ToString();
  150. BlobItemInfo blobbItemInfo = input.ToObject<BlobItemInfo>();
  151. //var response = oldBobCilent.GetBlobClient($"{blobItem.Name}").DownloadTo(meomoryStream);
  152. //BlobItemInfo blobbItemInfo = Encoding.UTF8.GetString(meomoryStream.ToArray()).ToString().ToObject<BlobItemInfo>();
  153. blobbItemInfo.exercise.periodId = cItem.newPrdId;
  154. blobbItemInfo.exercise.gradeIds = cItem.newGrId;
  155. blobbItemInfo.exercise.subjectId = cItem.newSubId;
  156. var urlSas = _azureStorage.GetBlobSAS($"{cItem.newSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List); //获取容器sas和有效期
  157. var ster = newBobCilent.UploadFileByContainer(blobbItemInfo.ToJsonString(), blobItem.Name, blobbItemInfo.id);
  158. }
  159. }
  160. }
  161. }
  162. return Ok(new { state = RespondCode.Ok});
  163. }
  164. /// <summary>
  165. /// 查询试卷的数量统计集合
  166. /// </summary>
  167. /// <param name="jsonElement"></param>
  168. /// <returns></returns>
  169. [ProducesDefaultResponseType]
  170. [HttpPost("get-count")]
  171. public async Task<IActionResult> GetCount(JsonElement jsonElement)
  172. {
  173. jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
  174. if(!jsonElement.TryGetProperty("term", out JsonElement term)) return BadRequest();
  175. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  176. var (start, end) = TimeHelper.GetTermStartOrEnd(DateTime.Now);
  177. var cosmosClient = _azureCosmos.GetCosmosClient();
  178. ////分开部署,就不需要,一站多用时,取消注释
  179. //if ($"{site}".Equals(BIConst.Global))
  180. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  181. object paperCount = new object();
  182. if (!string.IsNullOrEmpty($"{tmdId}"))
  183. {
  184. List<string> schoolIds = new();
  185. schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  186. List<SchoolPaper> schoolPapers = new();
  187. string time = "";
  188. bool bos = bool.Parse($"{term}");
  189. if (bos == true)
  190. {
  191. time = $" where c.createTime >={start} and c.createTime <={end}";
  192. }
  193. foreach (var schoolId in schoolIds)
  194. {
  195. StringBuilder sqlTxt = new("select value(count(c.id)) from c");
  196. if (bos != true)
  197. sqlTxt.Append($" where c.code='Paper-{schoolId}'");
  198. else
  199. {
  200. sqlTxt.Append(time);
  201. sqlTxt.Append($" and c.code='Paper-{schoolId}'");
  202. };
  203. School school = new();
  204. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("Base"));
  205. if (response.Status == 200)
  206. {
  207. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  208. school = json.ToObject<School>();
  209. }
  210. SchoolPaper schoolPaper = new() { id = schoolId, name = school != null ? school.name : schoolId };
  211. schoolPaper.totals = await CommonFind.GetSqlValueCount(cosmosClient, "School", sqlTxt.ToString());
  212. schoolPapers.Add(schoolPaper);
  213. }
  214. paperCount = schoolPapers;
  215. }
  216. else
  217. {
  218. StringBuilder sqlTxt = new ("select value(count(c.id)) from c where c.pk='Paper'");
  219. if (bool.Parse($"{term}") == true)
  220. {
  221. sqlTxt.Append($" and c.createTime >= {start} and c.createTime <={end}");
  222. }
  223. paperCount = await CommonFind.GetSqlValueCount(cosmosClient, "School", sqlTxt.ToString());
  224. }
  225. return Ok(new { state = 200 , paperCount });
  226. }
  227. /// <summary>
  228. /// 查询所有的试题数量
  229. /// </summary>
  230. /// <returns></returns>
  231. [ProducesDefaultResponseType]
  232. [HttpPost("get-total")]
  233. public async Task<IActionResult> GetTotal(JsonElement jsonElement)
  234. {
  235. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  236. var cosmosClient = _azureCosmos.GetCosmosClient();
  237. ////分开部署,就不需要,一站多用时,取消注释
  238. //if ($"{site}".Equals(BIConst.Global))
  239. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  240. string sqlTxt = $"select value(COUNT(c.id)) from c where c.pk='Paper'";
  241. long totals = await CommonFind.GetSqlValueCount(cosmosClient, "School", sqlTxt.ToString());
  242. return Ok(new { state = 200, totals });
  243. }
  244. /// <summary>
  245. /// 依据醍摩豆账户统计相关联的学校试卷数量
  246. /// </summary>
  247. /// <param name="jsonElement"></param>
  248. /// <returns></returns>
  249. [ProducesDefaultResponseType]
  250. [HttpPost("get-assistschool")]
  251. public async Task<IActionResult> GetAssistSchool(JsonElement jsonElement)
  252. {
  253. if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
  254. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  255. var cosmosClient = _azureCosmos.GetCosmosClient();
  256. ////分开部署,就不需要,一站多用时,取消注释
  257. //if ($"{site}".Equals(BIConst.Global))
  258. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  259. List<string> schoolIds = new();
  260. List<SchoolPaper> schoolPapers = new();
  261. schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  262. foreach (var schoolId in schoolIds)
  263. {
  264. School school = new();
  265. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("Base"));
  266. if (response.Status == 200)
  267. {
  268. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  269. school = json.ToObject<School>();
  270. }
  271. SchoolPaper schoolPaper = new() { id = schoolId , name = school != null ? school.name : schoolId };
  272. schoolPaper.totals = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(COUNT(c.id)) from c where c.code='Paper-{schoolId}'");
  273. schoolPapers.Add(schoolPaper);
  274. }
  275. return Ok(new { state = 200, schoolPapers });
  276. }
  277. /// <summary>
  278. /// 一年的12个月的
  279. /// </summary>
  280. /// <param name="jsonElement"></param>
  281. /// <returns></returns>
  282. [ProducesDefaultResponseType]
  283. [HttpPost("get-yerar")]
  284. public async Task<IActionResult> GetNewYear(JsonElement jsonElement)
  285. {
  286. jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
  287. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  288. var cosmosClient = _azureCosmos.GetCosmosClient();
  289. ////分开部署,就不需要,一站多用时,取消注释
  290. //if ($"{site}".Equals(BIConst.Global))
  291. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  292. List<MonthStartEnd> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
  293. if (string.IsNullOrEmpty($"{tmdId}"))
  294. {
  295. Dictionary<string, long> schoolYears = new Dictionary<string, long>();
  296. foreach (var temp in endList1)
  297. {
  298. string sqlText = $"SELECT value(COUNT(c.id)) FROM c WHERE c.createTime >= {temp.start} and c.createTime <= {temp.end} and c.pk='Paper'";
  299. long total = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School", "Teacher" }, sqlText);
  300. schoolYears.Add(temp.yearMonth, total);
  301. }
  302. return Ok(new { state = 200, schoolYears });
  303. }
  304. else
  305. {
  306. List<string> schoolIds = new();
  307. schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  308. List<SchoolYear> schoolYears = new();
  309. foreach (var schoolId in schoolIds)
  310. {
  311. School school = new();
  312. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("Base"));
  313. if (response.Status == 200)
  314. {
  315. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  316. school = json.ToObject<School>();
  317. }
  318. SchoolYear schoolYear = new() { id = schoolId, name = school != null ? school.name : schoolId };
  319. Dictionary<string, long> yearCount = new();
  320. foreach (var temp in endList1)
  321. {
  322. string sqlTxt = $"SELECT value(COUNT(c.id)) FROM c WHERE c.code='Paper-{schoolId}' and c.createTime >= {temp.start} and c.createTime <= {temp.end} and c.pk='Paper'";
  323. long totals = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School", "Teacher" }, sqlTxt);
  324. yearCount.Add(temp.yearMonth, totals);
  325. }
  326. schoolYear.yearPaper = yearCount;
  327. schoolYears.Add(schoolYear);
  328. }
  329. return Ok(new { state = 200, schoolYears });
  330. }
  331. }
  332. /// <summary>
  333. /// 统计当前学期的数量,传醍摩豆则统计该账户相关的学校试题统计,不传则统计当前学期的试卷
  334. /// </summary>
  335. /// <param name="jsonElement"></param>
  336. /// <returns></returns>
  337. [ProducesDefaultResponseType]
  338. [HttpPost("get-termpaper")]
  339. public async Task<IActionResult> GetTermPaper(JsonElement jsonElement)
  340. {
  341. jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
  342. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  343. var cosmosClient = _azureCosmos.GetCosmosClient();
  344. ////分开部署,就不需要,一站多用时,取消注释
  345. //if ($"{site}".Equals(BIConst.Global))
  346. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  347. var (start, end) = TimeHelper.GetTermStartOrEnd(DateTime.Now);
  348. var totals = new object();
  349. if (!string.IsNullOrEmpty($"{tmdId}"))
  350. {
  351. List<SchoolPaper> schoolPapers = new();
  352. List<string> schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  353. foreach (var schoolId in schoolIds)
  354. {
  355. School school = new();
  356. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("Base"));
  357. if(response.Status == 200)
  358. {
  359. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  360. school = json.ToObject<School>();
  361. }
  362. SchoolPaper schoolPaper = new() { id = schoolId, name = school != null ? school.name : schoolId };
  363. string sqlTxt = $"select value(count(c.id)) from c where c.createTime >={start} and c.createTime <={end}";
  364. schoolPaper.totals += await CommonFind.GetSqlValueCount(cosmosClient, "School", sqlTxt, $"Paper-{schoolId}");
  365. //await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText:sqlTxt.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{schoolId}")}))
  366. //{
  367. // using var json = await JsonDocument.ParseAsync(item.ContentStream);
  368. // if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt32() > 0)
  369. // {
  370. // foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  371. // {
  372. // schoolPaper.totals += obj.GetProperty("totals").GetInt64();
  373. // }
  374. // }
  375. //}
  376. //schoolPaper.totals = await CommonFind.FindTotals(cosmosClient, sqlTxt, new List<string>() { "School" });
  377. schoolPapers.Add(schoolPaper);
  378. }
  379. totals = schoolPapers;
  380. }
  381. else
  382. {
  383. string sqlTxt = $"SELECT value(count(c.id)) FROM c where c.pk='Paper' and c.createTime >= {start} and c.createTime <= {end}";
  384. totals = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School" }, sqlTxt);
  385. }
  386. return Ok(new { state = 200, totals });
  387. }
  388. /// <summary>
  389. /// 依据试卷Id查询试卷信息 数据管理工具——查询工具
  390. /// </summary>
  391. /// <param name="jsonElement"></param>
  392. /// <returns></returns>
  393. [ProducesDefaultResponseType]
  394. [HttpPost("get-info")]
  395. public async Task<IActionResult> GetInfo(JsonElement jsonElement)
  396. {
  397. if (!jsonElement.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
  398. jsonElement.TryGetProperty("isPersonal", out JsonElement isPersonal);
  399. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  400. var cosmosClient = _azureCosmos.GetCosmosClient();
  401. ////分开部署,就不需要,一站多用时,取消注释
  402. //if ($"{site}".Equals(BIConst.Global))
  403. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  404. List<object> paperInfos = new();
  405. string sqlTxt = $"select * from c where c.id='{paperId}' and c.pk='Paper'";
  406. if (!string.IsNullOrEmpty($"{isPersonal}"))
  407. {
  408. string tableName = "School";
  409. if (bool.Parse($"{isPersonal}") == true)
  410. {
  411. tableName = "Teacher";
  412. }
  413. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", tableName).GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { }))
  414. {
  415. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  416. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  417. {
  418. paperInfos.Add(obj.ToObject<object>());
  419. }
  420. }
  421. }
  422. else
  423. {
  424. List<string> tableName = new(){ "School", "Teacher" };
  425. foreach (var temp in tableName)
  426. {
  427. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", temp).GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { }))
  428. {
  429. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  430. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  431. {
  432. paperInfos.Add(obj.ToObject<object>());
  433. }
  434. }
  435. }
  436. }
  437. return Ok(new { state = 200, paperInfos });
  438. }
  439. public record SchoolPaper
  440. {
  441. public string id { get; set; }
  442. public string name { get; set; }
  443. public long totals { get; set; }
  444. }
  445. public record SchoolYear
  446. {
  447. public string id { get; set; }
  448. public string name { get; set; }
  449. public Dictionary<string, long> yearPaper { get; set; }
  450. }
  451. public record CopyPaper
  452. {
  453. public string oldId { get; set; }
  454. public string oldSc { get; set; }
  455. public string newSc { get; set; }
  456. public string newPrdId { get; set; }
  457. public string newSubId { get; set; }
  458. public string newSubName { get; set; }
  459. public List<string> newGrId { get; set; }
  460. }
  461. }
  462. }