XkwServiceController.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. using Microsoft.AspNetCore.Mvc;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using TEAMModelOS.Models;
  7. using TEAMModelOS.SDK.DI;
  8. using System.Text.Json;
  9. using TEAMModelOS.SDK.Models;
  10. using Microsoft.AspNetCore.Http;
  11. using TEAMModelOS.SDK.Extension;
  12. using Azure.Cosmos;
  13. using System.Text;
  14. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  15. using Microsoft.Extensions.Options;
  16. using Azure.Messaging.ServiceBus;
  17. using Microsoft.Extensions.Configuration;
  18. using HTEXLib.COMM.Helpers;
  19. using TEAMModelOS.SDK;
  20. using System.IdentityModel.Tokens.Jwt;
  21. using TEAMModelOS.Services;
  22. using TEAMModelOS.SDK.Models.Service;
  23. using System.IO;
  24. using System.Dynamic;
  25. using Microsoft.AspNetCore.Authorization;
  26. using Azure.Storage.Blobs.Models;
  27. using static TEAMModelOS.SDK.Models.Teacher;
  28. using System.Web;
  29. using static TEAMModelOS.Controllers.FixDataController;
  30. using static TEAMModelOS.SDK.SchoolService;
  31. using Microsoft.AspNetCore.Hosting;
  32. using TEAMModelOS.Filter;
  33. using TEAMModelOS.Controllers.Third.Xkw;
  34. using Microsoft.Extensions.Primitives;
  35. using System.Net.Http;
  36. using TEAMModelOS.Controllers.Third.Xkw.Sdk;
  37. using TEAMModelOS.SDK.Models.Table;
  38. using System.Text.RegularExpressions;
  39. using HtmlAgilityPack;
  40. using TEAMModelOS.SDK.Helper.Security.ShaHash;
  41. namespace TEAMModelOS.Controllers.Third.Xkw
  42. {
  43. // <summary>
  44. /// 标准OAuth2
  45. /// </summary>
  46. ///
  47. [ProducesResponseType(StatusCodes.Status200OK)]
  48. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  49. //
  50. //[Route("")]
  51. [Route("xkw")]
  52. [ApiController]
  53. public class XkwServiceController: ControllerBase
  54. {
  55. private readonly SnowflakeId _snowflakeId;
  56. private readonly AzureCosmosFactory _azureCosmos;
  57. private readonly DingDing _dingDing;
  58. private readonly Option _option;
  59. private readonly AzureStorageFactory _azureStorage;
  60. private readonly AzureServiceBusFactory _serviceBus;
  61. private readonly AzureRedisFactory _azureRedis;
  62. private readonly CoreAPIHttpService _coreAPIHttpService;
  63. private readonly ThirdApisService _scsApisService;
  64. private readonly HttpTrigger _httpTrigger;
  65. private readonly IWebHostEnvironment _environment;
  66. private readonly XkwAPIHttpService _xkwAPIHttpService;
  67. /// <summary>
  68. /// 全角
  69. /// </summary>
  70. string[] aza = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
  71. /// <summary>
  72. /// 半角
  73. /// </summary>
  74. string[] azh = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
  75. public IConfiguration _configuration { get; set; }
  76. public XkwServiceController(XkwAPIHttpService xkwAPIHttpService, IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
  77. AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, ThirdApisService scsApisService, HttpTrigger httpTrigger)
  78. {
  79. _azureCosmos = azureCosmos;
  80. _snowflakeId = snowflakeId;
  81. _dingDing = dingDing;
  82. _option = option?.Value;
  83. _azureStorage = azureStorage;
  84. _serviceBus = serviceBus;
  85. _configuration = configuration;
  86. _azureRedis = azureRedis;
  87. _coreAPIHttpService = coreAPIHttpService;
  88. _scsApisService = scsApisService;
  89. _httpTrigger = httpTrigger;
  90. _environment = environment;
  91. _xkwAPIHttpService=xkwAPIHttpService;
  92. }
  93. [HttpGet("get-xkw-baseinfo")]
  94. //[Authorize(Roles = "IES")]
  95. //[AuthToken(Roles = "teacher,admin,area,student")]
  96. public async Task<IActionResult> GetXkwBaseInfo([FromQuery] OAuthCode authCode)
  97. {
  98. //var courses = _xkwAPIHttpService.Get<JsonElement>("/xopqbm/courses/all", null);
  99. List<XkwQuestionType> questionTypes = new List<XkwQuestionType>();
  100. XkwConstant.xkwCourses.ForEach(x =>
  101. {
  102. Dictionary<string, string> dict = new Dictionary<string, string>() { { "course_id", $"{x.id}" } };
  103. var question_types = _xkwAPIHttpService.Get<JsonElement>($"/xopqbm/question-types", dict);
  104. if (question_types.TryGetProperty("code", out JsonElement code) && $"{code}".Equals("2000000"))
  105. {
  106. questionTypes.AddRange(question_types.GetProperty("data").ToObject<List<XkwQuestionType>>());
  107. }
  108. });
  109. return Ok(questionTypes);
  110. }
  111. [HttpGet("paper-notice")]
  112. //[Authorize(Roles = "IES")]
  113. //[AuthToken(Roles = "teacher,admin,area,student")]
  114. public async Task<IActionResult> PaperNotice([FromQuery] OAuthCode authCode)
  115. {
  116. await _dingDing.SendBotMsg($"学科网推送消息:{authCode.ToJsonString()}", GroupNames.成都开发測試群組);
  117. return Ok(authCode);
  118. }
  119. //paperid=85602892&openid=open-322-TPllGeMdvY 包含填空题 综合题,判断题
  120. // paperid=85621779&openid=open-322-TPllGeMdvY 综合题
  121. [HttpPost("get-paper-items")]
  122. #if DEBUG
  123. #else
  124. [Authorize(Roles = "IES")]
  125. [AuthToken(Roles = "teacher,admin,area,student")]
  126. #endif
  127. public async Task<IActionResult> GetPaperItems(JsonElement json)
  128. {
  129. try
  130. {
  131. if (!json.TryGetProperty("paperid", out JsonElement paperid)) { return BadRequest(); }
  132. if (!json.TryGetProperty("openid", out JsonElement openid)) { return BadRequest(); }
  133. Dictionary<string, string> dict = new Dictionary<string, string>() { { "id", $"{paperid}" }, { "user_id", $"{openid}" } };
  134. var paper = _xkwAPIHttpService.Get<JsonElement>("/xopqbm/zj-saas/users/download-papers/details", dict);
  135. List<XkwItem> items = new List<XkwItem>();
  136. string ps = paper.ToJsonString();
  137. XkwDto course = null;
  138. List<XkwPaperPart> xkwPapers = new List<XkwPaperPart>();
  139. if (paper.TryGetProperty("code", out JsonElement code) && $"{code}".Equals("2000000"))
  140. {
  141. if (paper.TryGetProperty("data", out JsonElement data) && data.TryGetProperty("course_id", out JsonElement course_id))
  142. {
  143. course = XkwConstant.xkwCourses.Find(x => $"{course_id}".Equals($"{x.id}"));
  144. if (course != null)
  145. {
  146. if (data.TryGetProperty("body", out JsonElement body))
  147. {
  148. List<XkwPaperPart> paperParts = body.ToObject<List<XkwPaperPart>>();
  149. xkwPapers.AddRange(paperParts);
  150. items.AddRange(paperParts.SelectMany(x => x.part_body).SelectMany(z => z.questions));
  151. }
  152. }
  153. }
  154. }
  155. List<XkwItemInfo> itemInfos = new List<XkwItemInfo>();
  156. List<XkwDto> xkw_points = new List<XkwDto>();
  157. var kpoint_ids = items.Where(z=>z.kpoint_ids!=null).SelectMany(x => x.kpoint_ids).ToHashSet();
  158. if (kpoint_ids.Any())
  159. {
  160. Dictionary<string, string> dict_pointids = new Dictionary<string, string>() { { "ids", String.Join(",", kpoint_ids.Select(x => x)) } };
  161. var points = _xkwAPIHttpService.Get<JsonElement>("/xopqbm/knowledge-points", dict_pointids);
  162. if (points.TryGetProperty("code", out JsonElement pcode) && $"{pcode}".Equals("2000000"))
  163. {
  164. if (points.TryGetProperty("data", out JsonElement pdata))
  165. {
  166. xkw_points = pdata.ToObject<List<XkwDto>>();
  167. }
  168. }
  169. }
  170. int index = 1;
  171. items.ForEach(x => {
  172. //x.kpoint_ids
  173. //设置默认难度,和默认认知层次
  174. int field = 1;
  175. int level = 3;
  176. List<string> gradeNames = new List<string>();
  177. List<string> knowledge = new List<string>();
  178. bool objective = false;
  179. string tag = "";
  180. foreach (var difct in XkwConstant.xkwDifficulties)
  181. {
  182. if (x.difficulty < difct.ceiling && x.difficulty >= difct.flooring)
  183. {
  184. level = difct.level;
  185. }
  186. }
  187. var grades = XkwConstant.xkwGrades.FindAll(g =>x.grade_ids!=null && x.grade_ids.Contains(g.id));
  188. if (grades.IsNotEmpty())
  189. {
  190. gradeNames = grades.Select(g => g.name).ToList();
  191. }
  192. if (x.kpoint_ids.IsNotEmpty())
  193. {
  194. var points = xkw_points.FindAll(p => x.kpoint_ids.Contains(p.id));
  195. if (points.Any())
  196. {
  197. knowledge.AddRange(points.Select(x => x.name));
  198. }
  199. }
  200. var type = XkwConstant.xkwQuestionTypes.Find(t => t.id == x.type_id);
  201. //判断是否 主客观题
  202. if (type != null)
  203. {
  204. objective = type.objective;
  205. tag = type.name;
  206. }
  207. else
  208. {
  209. objective = false;
  210. }
  211. string classpattern = "class=\"([^\"]*)\"";
  212. string pattern = "<span([^>]{0,})>";
  213. string table_pattern = "<table([^>]{0,})>";
  214. string apattern = "<a([^>]{0,})></a>";
  215. string rg_qml_sq = "<div[^>]{0,}\\s*qml-sq[^>]{0,}>";
  216. //string stem = x.stem.Replace("</table>", "");
  217. string[] questiones = Regex.Split(x.stem, rg_qml_sq);
  218. string rg_qml_an_sq = "\\d+\\s*\\.\\s*<span[^>]{0,}\\s*qml-an-sq[^>]{0,}>" +
  219. "|(\\d+\\s*)\\s*<span[^>]{0,}\\s*qml-an-sq[^>]{0,}>" +
  220. "|\\d+\\s*<span[^>]{0,}\\s*qml-an-sq[^>]{0,}>" +
  221. "|(\\d+\\s*)\\s*<span[^>]{0,}\\s*qml-an-sq[^>]{0,}>";
  222. var answers = Regex.Split(x.answer, rg_qml_an_sq);
  223. string rg_qml_exps_sq = "<div[^>]{0,}\\s*exps-sq[^>]{0,}>";
  224. var explains = Regex.Split(x.explanation, rg_qml_exps_sq);
  225. if (questiones.Length > 1)
  226. {
  227. index += 1;
  228. XkwItemInfo itemInfo = new XkwItemInfo
  229. {
  230. source = 3,
  231. shaCode = ShaHashHelper.GetSHA1(x.stem),
  232. id = x.id,
  233. order = index,
  234. subjectName = course?.subject_name,
  235. periodName = course?.stage_name,
  236. field = field,
  237. level = level,
  238. gradeNames = gradeNames,
  239. knowledge = knowledge,
  240. objective = objective,
  241. tag = tag,
  242. question = questiones[0],
  243. type = "compose",
  244. };
  245. itemInfos.Add(itemInfo);
  246. for (int i = 1; i < questiones.Length; i++)
  247. {
  248. index += 1;
  249. XkwItemInfo child_itemInfo = new XkwItemInfo
  250. {
  251. pid = x.id,
  252. source = 3,
  253. id = $"{x.id}-{i}",
  254. order = index,
  255. subjectName = course?.subject_name,
  256. periodName = course?.stage_name,
  257. field = field,
  258. level = level,
  259. gradeNames = gradeNames,
  260. knowledge = knowledge,
  261. objective = objective,
  262. tag = "",
  263. };
  264. questiones[i] = questiones[i].Replace("<div class=\"qml-stem\"><br/>", "");
  265. if (questiones[i].Contains("qml-og"))
  266. {
  267. child_itemInfo.objective = true;
  268. string shtml = questiones[i];
  269. //去除class 以及span标签"
  270. // shtml = Regex.Replace(shtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
  271. //shtml = Regex.Replace(shtml, classpattern, "");
  272. //shtml = Regex.Replace(shtml, pattern, "");
  273. //shtml = Regex.Replace(shtml, apattern, "");
  274. //shtml = shtml.Replace(" close=\"\" separators=\" | \">", "");
  275. //shtml = shtml.Replace("\t", " ").Replace("<span>", "").Replace("</span>", "").Replace("dir=\"ltr\"", "");
  276. //处理 标签中包含的空格字符
  277. //处理题干
  278. (List<CodeValue> options, string question) = OptionProcess(shtml);
  279. child_itemInfo.option = options;
  280. child_itemInfo.opts = options.Count;
  281. child_itemInfo.question = question;
  282. //处理答案
  283. //去除class 以及span标签"
  284. if (answers.Length - 1 >= i)
  285. {
  286. string ahtml = answers[i];
  287. ahtml = Regex.Replace(ahtml, classpattern, "");
  288. ahtml = Regex.Replace(ahtml, pattern, "");
  289. ahtml = Regex.Replace(ahtml, apattern, "");
  290. ahtml = ahtml.Replace(" close=\"\" separators=\" | \">", "");
  291. ahtml = ahtml.Replace("\t", " ").Replace("<span>", "").Replace("</span>", "").Replace("dir=\"ltr\"", "");
  292. HashSet<string> ans = new HashSet<string>();
  293. var anstr = BlankTag(ahtml);
  294. for (int idx = 0; idx < 26; idx++)
  295. {
  296. anstr = anstr.Replace(aza[idx], azh[idx]);
  297. }
  298. anstr.Select(s => s.ToString()).ToList().ForEach(x =>
  299. {
  300. ans.Add(x);
  301. });
  302. child_itemInfo.answerHtml = answers[0];
  303. child_itemInfo.answer = ans.ToList();
  304. child_itemInfo.objective = true;
  305. if (child_itemInfo.opts > 0)
  306. {
  307. if (ans.Count > 1)
  308. {
  309. child_itemInfo.type = "multiple";
  310. }
  311. else
  312. {
  313. child_itemInfo.type = "single";
  314. }
  315. }
  316. else
  317. {
  318. if (child_itemInfo.answer.Any()
  319. &&(child_itemInfo.answer.First().Equals("√") || child_itemInfo.answer.First().Equals("×")
  320. || child_itemInfo.answer.First().Equals("对") || child_itemInfo.answer.First().Equals("错")
  321. || child_itemInfo.answer.First().Equals("正确") || child_itemInfo.answer.First().Equals("错误")))
  322. {
  323. child_itemInfo.type = "judge";
  324. child_itemInfo.opts = 2;
  325. child_itemInfo.option = new List<CodeValue>() { new CodeValue { code = "A", value = "对" }, new CodeValue { code = "B", value = "错" } };
  326. child_itemInfo.answer = itemInfo.answer.First().Equals("√") || child_itemInfo.answer.First().Equals("对")|| child_itemInfo.answer.First().Equals("正确") ? new List<string> { "A" } : new List<string> { "B" };
  327. }
  328. else
  329. {
  330. child_itemInfo.objective = false;
  331. child_itemInfo.type = "subjective";
  332. }
  333. }
  334. }
  335. //处理解析
  336. if (explains.Length - 1 >= i)
  337. {
  338. child_itemInfo.explain = explains[i];
  339. }
  340. }
  341. else
  342. {
  343. child_itemInfo.type = "subjective";
  344. child_itemInfo.objective = false;
  345. if (explains.Length - 1 >= i)
  346. {
  347. child_itemInfo.explain = explains[i];
  348. }
  349. string ansstr = "";
  350. if (answers.Length - 1 >= i)
  351. {
  352. child_itemInfo.answer = new List<string> { answers[i] };
  353. ansstr = HtmlHelper.DoUselessTag(answers[i]);
  354. }
  355. child_itemInfo.question = questiones[i];
  356. if (ansstr.Equals("√") || ansstr.Equals("×")
  357. || ansstr.Equals("对") || ansstr.Equals("错")
  358. || ansstr.Equals("正确") || ansstr.Equals("错误"))
  359. {
  360. child_itemInfo.objective = true;
  361. child_itemInfo.type = "judge";
  362. child_itemInfo.opts = 2;
  363. child_itemInfo.option = new List<CodeValue>() { new CodeValue { code = "A", value = "对" }, new CodeValue { code = "B", value = "错" } };
  364. child_itemInfo.answer = ansstr.Equals("√") || ansstr.Equals("对") || ansstr.Equals("正确") ? new List<string> { "A" } : new List<string> { "B" };
  365. }
  366. }
  367. string rg_ques_no = "<span[^>]{0,}\\s*ques-no[^>]{0,}>[\\s\\S]*?</span>";
  368. child_itemInfo.question = Regex.Replace(child_itemInfo.question, rg_ques_no, "");
  369. child_itemInfo.shaCode = ShaHashHelper.GetSHA1(child_itemInfo.question);
  370. itemInfo.children.Add(child_itemInfo);
  371. //itemInfos.Add(child_itemInfo);
  372. }
  373. }
  374. else
  375. {
  376. XkwItemInfo itemInfo = new XkwItemInfo
  377. {
  378. source = 3,
  379. shaCode = ShaHashHelper.GetSHA1(x.stem),
  380. id = x.id,
  381. order = index,
  382. explain = x.explanation,
  383. subjectName = course?.subject_name,
  384. periodName = course?.stage_name,
  385. // explain = x.explanation.Replace("【分析】", "分析:").Replace("【详解】", "详解:")
  386. field = field,
  387. level = level,
  388. gradeNames = gradeNames,
  389. knowledge = knowledge,
  390. objective = objective,
  391. tag = tag
  392. };
  393. index += 1;
  394. //如果是客观题,则需要处理选项和答案。
  395. if (itemInfo.objective)
  396. {
  397. string shtml = x.stem;
  398. //去除class 以及span标签"
  399. // shtml = Regex.Replace(shtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
  400. //shtml = Regex.Replace(shtml, classpattern, "");
  401. //shtml = Regex.Replace(shtml, pattern, "");
  402. //shtml = Regex.Replace(shtml, apattern, "");
  403. //shtml = shtml.Replace(" close=\"\" separators=\" | \">", "");
  404. //shtml = shtml.Replace("\t", " ").Replace("<span>", "").Replace("</span>", "").Replace("dir=\"ltr\"", "");
  405. //处理 标签中包含的空格字符
  406. //处理题干
  407. (List<CodeValue> options, string question) = OptionProcess(shtml);
  408. itemInfo.option = options;
  409. itemInfo.opts = options.Count;
  410. itemInfo.question = question;
  411. itemInfo.objective = true;
  412. //处理答案
  413. //去除class 以及span标签"
  414. string ahtml = x.answer;
  415. ahtml = Regex.Replace(ahtml, classpattern, "");
  416. ahtml = Regex.Replace(ahtml, pattern, "");
  417. ahtml = Regex.Replace(ahtml, apattern, "");
  418. ahtml = ahtml.Replace(" close=\"\" separators=\" | \">", "");
  419. ahtml = ahtml.Replace("\t", " ").Replace("<span>", "").Replace("</span>", "").Replace("dir=\"ltr\"", "");
  420. HashSet<string> ans = new HashSet<string>();
  421. var anstr = BlankTag(ahtml);
  422. for (int idx = 0; idx < 26; idx++)
  423. {
  424. anstr = anstr.Replace(aza[idx], azh[idx]);
  425. }
  426. anstr.Select(s => s.ToString()).ToList().ForEach(x =>
  427. {
  428. ans.Add(x);
  429. });
  430. itemInfo.answerHtml = x.answer;
  431. itemInfo.answer = ans.ToList();
  432. if (itemInfo.opts > 0)
  433. {
  434. if (ans.Count > 1)
  435. {
  436. itemInfo.type = "multiple";
  437. }
  438. else
  439. {
  440. itemInfo.type = "single";
  441. }
  442. }
  443. else {
  444. if (itemInfo.answer.Any()
  445. && (itemInfo.answer.First().Equals("√") || itemInfo.answer.First().Equals("×")
  446. || itemInfo.answer.First().Equals("对") || itemInfo.answer.First().Equals("错")
  447. || itemInfo.answer.First().Equals("正确") || itemInfo.answer.First().Equals("错误")))
  448. {
  449. itemInfo.type = "judge";
  450. itemInfo.opts = 2;
  451. itemInfo.option = new List<CodeValue>() { new CodeValue { code = "A", value = "对" }, new CodeValue { code = "B", value = "错" } };
  452. itemInfo.answer = itemInfo.answer.First().Equals("√") || itemInfo.answer.First().Equals("对") || itemInfo.answer.First().Equals("正确") ? new List<string> { "A" } : new List<string> { "B" };
  453. }
  454. else
  455. {
  456. itemInfo.objective = false;
  457. itemInfo.type = "subjective";
  458. }
  459. }
  460. }
  461. else
  462. {
  463. itemInfo.type = "subjective";
  464. itemInfo.question = x.stem;
  465. itemInfo.answer = new List<string>() { HtmlHelper.DoUselessTag(x.answer.ToString()) };
  466. if (itemInfo.answer.First().Equals("√") || itemInfo.answer.First().Equals("×")
  467. || itemInfo.answer.First().Equals("对") || itemInfo.answer.First().Equals("错")
  468. || itemInfo.answer.First().Equals("正确") || itemInfo.answer.First().Equals("错误"))
  469. {
  470. itemInfo.objective = true;
  471. itemInfo.type = "judge";
  472. itemInfo.opts = 2;
  473. itemInfo.option = new List<CodeValue>() { new CodeValue { code = "A", value = "对" }, new CodeValue { code = "B", value = "错" } };
  474. itemInfo.answer = itemInfo.answer.First().Equals("√") || itemInfo.answer.First().Equals("对") || itemInfo.answer.First().Equals("正确") ? new List<string> { "A" } : new List<string> { "B" };
  475. }
  476. }
  477. itemInfos.Add(itemInfo);
  478. }
  479. });
  480. HashSet<string> gradeNames = new HashSet<string>();
  481. gradeNames = itemInfos.SelectMany(x => x.gradeNames).ToHashSet();
  482. // await _dingDing.SendBotMsg($"学科网推送消息:{authCode.ToJsonString()}", GroupNames.成都开发測試群組);
  483. return Ok(new { xkwPapers, periodName = course.stage_name, subjectName = course.subject_name, gradeNames, knowledge = xkw_points.Select(x => x.name), itemInfos, paper });
  484. } catch (Exception ex) {
  485. if (ex.Message.Contains("客户已关闭") || ex.Message.Contains("403")||ex.Message.Contains("参数无效"))
  486. {
  487. return Ok(new { error = 403, message="学科网该账号授权已到期!" });
  488. }
  489. else
  490. {
  491. await _dingDing.SendBotMsg($"学科网组卷错误:{ex.Message}\n{ex.StackTrace}\n{json.ToJsonString()}", GroupNames.成都开发測試群組);
  492. return BadRequest($"学科网组卷错误:{ex.Message}\n{ex.StackTrace}\n{json.ToJsonString()}");
  493. }
  494. }
  495. }
  496. private string BlankTag(string tagHtml)
  497. {
  498. //去掉标签中的Html
  499. HtmlDocument doc = new HtmlDocument();
  500. doc.LoadHtml(tagHtml);
  501. var tagValue = doc.DocumentNode.InnerText.Replace("{", "").Replace("}", "")
  502. .Replace("\n", "").Replace(" ", "").Replace("\t", "").Replace("\r", "")
  503. .Replace("&nbsp;", "").Replace("&emsp;", "").Replace("&emsp;", "");
  504. // tagValue = Regex.Replace(tagValue, @"\d", "");
  505. tagValue = Regex.Replace(tagValue, @"\s", "");
  506. return tagValue;
  507. }
  508. public (List<CodeValue> options, string question) OptionProcess(string question) {
  509. string Options = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  510. string[] optionsKeys = Options.Select(s => s.ToString()).ToArray();
  511. for (int idx = 0; idx < 26; idx++)
  512. {
  513. question = question.Replace(aza[idx], azh[idx]);
  514. }
  515. List<CodeValue> options = new List<CodeValue>();
  516. string optsRgex = optionsKeys[0] + "\\s*(\\.|\\.|\\、|\\:|\\:)([\\s\\S]*?).*"; ;
  517. string optsHtml = Regex.Match(question, optsRgex).Value;
  518. StringBuilder textImg = new StringBuilder();
  519. for (int i = 0; i < optionsKeys.Length - 1; i++)
  520. {
  521. string optRgex = optionsKeys[i] + "\\s*(\\.|\\.|\\、|\\:|\\:)([\\s\\S]*?)" + optionsKeys[i + 1] + "\\s*(\\.|\\.|\\、|\\:|\\:)";
  522. string optHtml = Regex.Match(optsHtml, optRgex).Value;
  523. if (string.IsNullOrWhiteSpace(optHtml))
  524. {
  525. optRgex = optionsKeys[i] + "\\s*(\\.|\\.|\\、|\\:|\\:).*";
  526. optHtml = Regex.Match(optsHtml, optRgex).Value;
  527. }
  528. if (!string.IsNullOrEmpty(optHtml))
  529. {
  530. optHtml = Regex.Replace(optHtml, optionsKeys[i + 1] + "\\s*(\\.|\\.|\\、|\\:|\\:)", "");
  531. optHtml = optHtml.Substring(2, optHtml.Length - 2);
  532. optHtml = HtmlHelper.DoUselessTag(optHtml);
  533. optHtml = optHtml.TrimStart().TrimEnd();
  534. textImg.Append(HtmlHelper.DoTextImg(optHtml));
  535. string table_pattern = "<table([^>]{0,})>";
  536. optHtml = Regex.Replace(optHtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
  537. options.Add(new CodeValue { code = optionsKeys[i], value = optHtml });
  538. }
  539. }
  540. if (!string.IsNullOrWhiteSpace(optsHtml))
  541. { question = question.Replace(optsHtml, "").Replace("<table class=\"qml-og\" style=\"width:100%\"><tr><td>", "");
  542. return (options, question);
  543. }
  544. else
  545. {
  546. question= question.Replace("<table class=\"qml-og\" style=\"width:100%\"><tr><td>","");
  547. return (new List<CodeValue>(), question);
  548. }
  549. }
  550. }
  551. }