123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- using Microsoft.IdentityModel.Tokens;
- using System;
- using System.Collections.Generic;
- using System.IdentityModel.Tokens.Jwt;
- using System.Security.Claims;
- using System.Text;
- using System.Text.Json;
- using System.Threading.Tasks;
- using System.Web;
- using TEAMModelOS.Filter;
- using TEAMModelOS.SDK;
- using TEAMModelOS.SDK.Models;
- using TEAMModelOS.SDK.Extension;
- using DocumentFormat.OpenXml.Wordprocessing;
- using System.Linq;
- using System.Net.Http;
- using System.Net.Http.Json;
- using System.Net;
- using System.Net.Http.Headers;
- using HTEXLib.COMM.Helpers;
- using TEAMModelOS.SDK.DI;
- using HTEXLib.Helpers.ShapeHelpers;
- using HtmlAgilityPack;
- using Top.Api.Util;
- using DocumentFormat.OpenXml.Drawing.Charts;
- using DocumentFormat.OpenXml.Spreadsheet;
- using TEAMModelOS.SDK.Models.Cosmos.School;
- using OfficeOpenXml;
- using System.IO.Packaging;
- using Microsoft.Azure.Amqp.Framing;
- using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
- using DocumentFormat.OpenXml.Office2010.Excel;
- using TEAMModelOS.SDK.Models.Service;
- namespace TEAMModelOS.Controllers.Third.Moofen
- {
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- [ApiController]
- public class MoofenController : ControllerBase
- {
- private readonly CoreAPIHttpService _coreAPIHttpService;
- private readonly IConfiguration _configuration;
- private readonly IHttpClientFactory _httpClient;
- private readonly DingDing _dingDing;
- private readonly AzureCosmosFactory _azureCosmos;
- private readonly AzureStorageFactory _azureStorage;
- public MoofenController(AzureCosmosFactory azureCosmos,CoreAPIHttpService coreAPIHttpService, IConfiguration configuration, IHttpClientFactory httpClient, DingDing dingDing,AzureStorageFactory azureStorage)
- {
- _coreAPIHttpService=coreAPIHttpService;
- _configuration=configuration;
- _httpClient=httpClient;
- _dingDing=dingDing;
- _azureCosmos=azureCosmos;
- _azureStorage=azureStorage;
- }
- [HttpPost("moofen/read-excel-knowledge-point")]
- [RequestSizeLimit(102_400_000_00)] //最大10000m左右
- public async Task<IActionResult> ReadExcelKnowledgePoint([FromForm] IFormFile[] file)
- {
-
- ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
- List<dynamic> period_subject = new List<dynamic>();
- foreach (var f in file)
- {
- List<MoofenKnowledgePointDto> pointDtos = new List<MoofenKnowledgePointDto>();
- string[] parts = f.FileName.Split(']');
- string[] periodp = parts[0].Split('[');
- string[] subjectp = parts[1].Split('[');
-
- string period = periodp[1].Trim();
- string subject = subjectp[1].Trim();
- List<string> titles = new List<string>();
- List<List<string>> datas = new List<List<string>>();
- using (ExcelPackage package = new ExcelPackage(f.OpenReadStream()))
- {
- ExcelWorksheets sheets = package.Workbook.Worksheets;
- var sheet = sheets.FirstOrDefault();
- if (sheet!= null)
- {
-
- var rows = sheet.Dimension.Rows;
- var columns = sheet.Dimension.Columns;
- for (int r = 1; r <= rows; r++)
- {
- List<string> data = new List<string>();
- for (int c = 1; c <= columns; c++)
- {
- var value = sheet .GetValue(r, c);
- if (r == 1)
- {
- if (!string.IsNullOrWhiteSpace($"{value}"))
- {
- titles.Add($"{value}");
- }
- else
- {
- break;
- }
- }
- else
- {
- if (c > titles.Count)
- {
- break;
- }
- else
- {
- data.Add($"{value}");
- }
- }
- }
- if (data.Any())
- {
- datas.Add(data);
- }
- }
- }
- }
-
- foreach ( var data in datas )
- {
- MoofenKnowledgePointDto knowledgePointDto = new MoofenKnowledgePointDto { kp1 = data[0] , kp2= data[1], kp3 = data[2], kp4= data[3], id= data[4] };
- if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp1)) {
- knowledgePointDto.level=1;
- knowledgePointDto.name=knowledgePointDto.kp1;
- }
- if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp2))
- {
- knowledgePointDto.level=2;
- knowledgePointDto.name=knowledgePointDto.kp2;
- }
- if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp3))
- {
- knowledgePointDto.level=3;
- knowledgePointDto.name=knowledgePointDto.kp3;
- }
- if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp4))
- {
- knowledgePointDto.level=4;
- knowledgePointDto.name=knowledgePointDto.kp4;
- }
- pointDtos.Add( knowledgePointDto );
- }
- // 构建树形结构
- var tree =KnowledgeService. BuildTree(pointDtos);
- tree.name=$"{period}-{subject}";
- var json= tree.children.ToJsonString();
- string subjectId = string.Empty;
- string periodId = string.Empty;
- switch (period)
- {
- case "小学": periodId="primary"; break;
- case "初中": periodId="junior"; break;
- case "高中": periodId="senior"; break;
- }
- switch (subject)
- {
- case "语文":
- subjectId="subject_chinese";
- break;
- case "数学":
- subjectId="subject_math";
- break;
- case "英语":
- subjectId="subject_english";
- break;
- case "物理":
- subjectId="subject_physics";
- break;
- case "化学":
- subjectId="subject_chemistry";
- break;
- case "生物":
- subjectId="subject_biology";
- break;
- case "政治":
- subjectId="subject_politics";
- break;
- case "历史":
- subjectId="subject_history";
- break;
- case "地理":
- subjectId="subject_geography";
- break;
- }
- period_subject.Add(new { period,subject, periodId,subjectId }) ;
- await _azureStorage.GetBlobContainerClient(Constant.teammodelos_blob).UploadFileByContainer(json,"third",$"moofen/kp-{periodId}-{subjectId}.json",true);
- }
- return Ok(new { period_subject });
- }
-
- [HttpPost("moofen/question")]
- [AuthToken(Roles = "teacher,admin")]
- #if !DEBUG
- [Authorize(Roles = "IES")]
- #endif
- public async Task<IActionResult> Question(JsonElement json)
- {
- var tokenData= HttpContext.GetAuthTokenInfo();
- string content = string.Empty;
- try {
- School school = null;
- Dictionary<string, string> dict = new Dictionary<string, string>();
- if (json.TryGetProperty("search", out JsonElement search) && !string.IsNullOrWhiteSpace($"{search}"))
- {
- dict.Add("search", $"{search}");
- }
- if (json.TryGetProperty("isSchoolItem", out JsonElement schoolItem) && schoolItem.ValueKind.Equals(JsonValueKind.True) &&!string.IsNullOrWhiteSpace(tokenData.school))
- {
- dict.Add("exSchId", $"{tokenData.school}");
- school= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(tokenData.school, new Azure.Cosmos.PartitionKey("Base"));
- }
- if (json.TryGetProperty("subject", out JsonElement subject) && !string.IsNullOrWhiteSpace($"{subject}"))
- {
- dict.Add("subject", $"{subject}");
- }
- if (json.TryGetProperty("kpIds", out JsonElement kpIds) && kpIds.ValueKind.Equals(JsonValueKind.Array))
- {
- //对方接口数据参数是"kpIds": "[\"221206\"]",
- dict.Add("kpIds", $"{kpIds.ToJsonString()}");
- }
- if (json.TryGetProperty("grades", out JsonElement grades) && !string.IsNullOrWhiteSpace($"{grades}"))
- {
- dict.Add("grades", $"{grades}");
- }
- if (json.TryGetProperty("type", out JsonElement type) && !string.IsNullOrWhiteSpace($"{type}"))
- {
- dict.Add("type", $"{type}");
- }
- if (json.TryGetProperty("difficulty", out JsonElement difficulty) && !string.IsNullOrWhiteSpace($"{difficulty}"))
- {
- dict.Add("difficulty", $"{difficulty}");
- }
- if (json.TryGetProperty("year", out JsonElement year) && !string.IsNullOrWhiteSpace($"{year}"))
- {
- dict.Add("year", $"{year}");
- }
- if (json.TryGetProperty("hasKps", out JsonElement hasKps) && !string.IsNullOrWhiteSpace($"{hasKps}"))
- {
- dict.Add("hasKps", $"{hasKps}");
- }
- if (json.TryGetProperty("hasAnswer", out JsonElement hasAnswer) && !string.IsNullOrWhiteSpace($"{hasAnswer}"))
- {
- dict.Add("hasAnswer", $"{hasAnswer}");
- }
- if (json.TryGetProperty("pageSize", out JsonElement pageSize) && !string.IsNullOrWhiteSpace($"{pageSize}"))
- {
- dict.Add("pageSize", $"{pageSize}");
- }
- if (json.TryGetProperty("currentPage", out JsonElement currentPage) && !string.IsNullOrWhiteSpace($"{currentPage}"))
- {
- dict.Add("currentPage", $"{currentPage}");
- }
- dict.Add("signKey", "TMD");
- var keys = dict.Keys.OrderBy(x => x);
- var parmas = string.Join("&", keys.Select(x => $"{x}={dict[x]}"));
- var signtime = DateTimeOffset.UtcNow.GetGMTTime(8).ToUnixTimeSeconds();
- parmas=$"{parmas}&signtime={signtime}";
- string sign = Md5Hash.Encrypt(parmas);
- dict.Add("signtime", $"{signtime}");
- dict.Add("sign", $"{sign}");
- dict.Remove("signKey");
- var pkeys = dict.Keys;
- string url = "http://www.moofen.net/esi/tmd/question/list";
- parmas= string.Join("&", pkeys.Select(x => $"{x}={dict[x]}"));
- var httpClient = _httpClient.CreateClient();
- var request = new HttpRequestMessage();
- request.Method = new HttpMethod("POST");
- request.RequestUri = new Uri(url);
- request.Content = new FormUrlEncodedContent(dict);
- // 设置请求头中的Content-Type
- // httpClient.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");
- var mediaTypeHeader = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
- mediaTypeHeader.CharSet = "UTF-8";
- request.Content.Headers.ContentType=mediaTypeHeader;
- HttpResponseMessage response = await _httpClient.CreateClient().SendAsync(request);
- List<MoofenItemInfo> items = new List<MoofenItemInfo>();
- if (response.StatusCode.Equals(HttpStatusCode.OK))
- {
- content = await response.Content.ReadAsStringAsync();
- var data = content.ToObject<JsonElement>();
- int count = 0;
- if (data.TryGetProperty("data", out JsonElement _data) )
- {
- if (_data.TryGetProperty("total", out JsonElement _total) && int.TryParse($"{_total}", out count))
- {
- if (_data.TryGetProperty("data", out JsonElement __data))
- {
- List<MoofenQuestion> questions = __data.ToObject<List<MoofenQuestion>>();
-
- items = MoofenQS(questions, $"{subject}", schoolId: $"{tokenData.school}", pquestion: null,level:-1);
- //foreach (var item in items)
- //{
- // //break;
- // string urlAI = "https://appraisal-test.teammodel.cn/ai/chat/completion";
- // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
- // var contentAI = new StringContent(JsonSerializer.Serialize(new
- // {
- // // appId = "5ac43c20-221e-4564-829d-15680ad761df",
- // appId = "eef773fd-85e7-4c2b-a6f7-e667af2f4f45",
- // sessionId = "",
- // text = item.description,
- // }), Encoding.UTF8, "application/json");
- // var httpreq = new HttpRequestMessage(HttpMethod.Post, urlAI) { Content = contentAI };
- // var authtoken = HttpContext.GetXAuth("AuthToken");
- // if (!httpClient.DefaultRequestHeaders.Contains("X-Auth-Authtoken"))
- // {
- // httpClient.DefaultRequestHeaders.Add("X-Auth-Authtoken", authtoken);
- // }
- // var AuthorizationToken = HttpContext.GetAuthorization();
- // if (httpClient.DefaultRequestHeaders.Contains("Authorization"))
- // {
- // httpClient.DefaultRequestHeaders.Remove("Authorization");
- // }
- // httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {AuthorizationToken}");
- // httpClient.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
- // var responseAI = await httpClient.SendAsync(httpreq, HttpCompletionOption.ResponseHeadersRead);
- // if (responseAI.StatusCode==HttpStatusCode.OK)
- // {
- // StringBuilder dataAI = new StringBuilder();
- // // 读取响应内容的异步流
- // using (var responseStream = await responseAI.Content.ReadAsStreamAsync())
- // {
- // //Debug.Print("============start response use minseconds=" + (DateTime.Now - d).TotalMilliseconds + " =================\r\n");
- // // 逐块读取并处理响应内容
- // var buffer = new byte[1024];
- // int bytesRead;
- // while ((bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
- // {
- // // 处理响应内容
- // string contentData = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);
- // if (contentData.Contains("data:"))
- // {
- // contentData = contentData.Replace("data:", "").Replace("[DONE]", "");
- // }
- // if (contentData.Contains("[DONE]"))
- // {
- // contentData = contentData.Replace("data:", "").Replace("[DONE]", "");
- // }
- // dataAI.Append(contentData);
- // }
- // }
- // item.explain=dataAI.ToString();
- // }
- //}
- }
- }
-
- }
-
- return Ok(new { code = 200, data, items , count });
- }
- else
- {
- content = await response.Content.ReadAsStringAsync();
- return Ok(new { code = response.StatusCode, data = content }) ;
- }
- } catch (Exception ex) {
- await _dingDing.SendBotMsg($"多分题目异常{ex.Message}\n{ex.StackTrace}",GroupNames.成都开发測試群組);
- return Ok(new { code = 500,msg=$"{ex.Message}",data= content });
- }
- }
- private List<MoofenItemInfo> MoofenQS(List<MoofenQuestion> questions, string subject,string pquestion,string schoolId, int level, string pid = null)
- {
- List<MoofenItemInfo> items = new List<MoofenItemInfo>();
- if (questions.IsNotEmpty())
- {
- //综合题 子题id处理
- if (!string.IsNullOrWhiteSpace(pid)) {
- int index = 1;
- foreach (MoofenQuestion question in questions) {
- question.questionCode= $"{pid}_{index}";
- question.difficulty=level;
- index++;
- }
- }
- foreach(var x in questions) {
- MoofenItemInfo item = new MoofenItemInfo()
- {
- id=x.questionCode,
- source=4,
- question=x.trunk,
- option=x.options?.Select(x => new CodeValue { code=x.label, value=x.content }).ToList(),
- level=x.difficulty,
- knowledge=x.kps?.Select(x => x.kpName).ToList(),
- grade=x.scope?.grade?.code,
- gradeName=x.scope?.grade?.name,
- subject=subject,
- pid=pid,
- code=!string.IsNullOrWhiteSpace(schoolId)?$"{schoolId}":null,
- pk="Item",
- scope=!string.IsNullOrWhiteSpace(schoolId) ? "school" : null,
- };
- //
- StringBuilder description = new StringBuilder($"科目:{subject}") ;
- if (!string.IsNullOrWhiteSpace(pquestion)) {
- description.AppendLine($";综合题:{pquestion}");
- }
- //处理年级转换
- if (!string.IsNullOrWhiteSpace(x.scope?.grade?.code) ) {
- item.gradeIds= new List<string>() { x.scope?.grade?.code };
- }
- if (!string.IsNullOrWhiteSpace(x.type?.code))
- {
- switch (x.type.code)
- {
- //选择
- case "C":
- var lables = x.options?.Where(y => y.correct==true).Select(v => v.label);
- if (lables!=null)
- {
- item.answer=lables.ToList();
- }
- item.objective=true;
- item.type="single";
- if (item.answer!=null && item.answer.Count()>1)
- {
- item.type="multiple";
- }
- if (x.options.IsNotEmpty())
- {
- item.opts=x.options.Count();
- }
- item.field=1;
- description.AppendLine(";题型:选择题");
- break;
- //填空
- case "F":
- var fills = x.items?.Select(b => b.content);
- if (fills!=null)
- {
- item.answer=fills.ToList();
- item.blankCount=fills.Count();
- }
- item.type="complete";
- item.field=2;
- description.AppendLine(";题型:填空题");
- break;
- //问答
- case "Q":
- if (!string.IsNullOrWhiteSpace(x.content))
- {
- item.answer=new List<string>() { x.content };
- }
- item.type="subjective";
- description.AppendLine(";题型:问答题");
- item.field=4;
- break;
- //写作
- case "W":
- if (!string.IsNullOrWhiteSpace(x.content))
- {
- item.answer=new List<string>() { x.content };
- }
- item.type="subjective";
- description.AppendLine(";题型:写作题");
- item.field=6;
- break;
- //综合
- case "S":
- item.type="compose";
- item.field=3;
- if (x.questions.IsNotEmpty() && x.questions.Count>0) {
- item.children.AddRange(MoofenQS(x.questions,subject: subject,pquestion: item.question,schoolId:schoolId,pid: item.id,level:x.difficulty));
- }
- description.AppendLine(";题型:综合题");
- break;
- }
- }
- StringBuilder sb = new StringBuilder($"{item.question}");
- if (item.option.IsNotEmpty()) {
- foreach (var option in item.option)
- {
- sb.Append(option.value);
- }
- }
- if (item.children.IsNotEmpty()) {
- foreach(var child in item.children)
- {
- sb.Append(child.question);
- if (child.option.IsNotEmpty())
- {
- foreach (var option in child.option)
- {
- sb.Append(option.value);
- }
- }
- }
- }
- string unhtml = HtmlHelper.DoUselessTag(sb.ToString());
- description.AppendLine($";题干:{item.question}");
- if (item.option.IsNotEmpty())
- {
- description.AppendLine($";选项:");
- foreach (var option in item.option) {
- description.AppendLine($"{option.code}:{option.value}");
- }
- }
- if(item.answer.IsNotEmpty())
- {
- description.AppendLine($";答案:{string.Join(",",item.answer)}");
- }
- if (item.knowledge.IsNotEmpty()) {
- description.AppendLine($";知识点:{string.Join(",", item.knowledge)}");
- }
- //HtmlDocument doc = new HtmlDocument();
- //doc.LoadHtml(description.ToString());
- item.description = description.ToString().Replace("\r\n","").Replace(" ","").Replace("\n\n","").Replace("“","").Replace("”","").Replace("<br />","").Replace("<!--EA-->","").Replace("<!--BA-->","")
- .Replace("</sup>","").Replace("<sup>", "").Replace("<u>", "").Replace("</u>", "");
- item.shaCode= ShaHashHelper.GetSHA1(unhtml);
- items.Add(item);
- }
- }
- return items;
- }
- [HttpPost("moofen/sso")]
- [AuthToken(Roles = "teacher,admin")]
- [Authorize(Roles = "IES")]
- public async Task<IActionResult> Sso(JsonElement json)
- {
- (string _id, _, _, string school) = HttpContext.GetAuthTokenInfo();
- CoreUser core = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string>()
- { { "key",$"{_id}" }
- }, "China", _configuration
- );
- if ( !string.IsNullOrWhiteSpace(core?.mobile))
- {
- string key = "U@vY42qlgq9ASXLXNqfze%Jj-NQ!ZKrX$iKonXy1u^8F021c7bzo@t5$ANwWCor#";
- string code = core?.mobile; //手机号码
- var claims = new[]
- {
- new Claim("code",code)
- };
- var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
- var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
- var jwt = new JwtSecurityToken(
- claims: claims,
- expires: DateTime.Now.AddMinutes(5),
- signingCredentials: signinCredentials
- );
- var tokenString = new JwtSecurityTokenHandler().WriteToken(jwt);
- string url = $"http://www.moofen.net/sso/tmodel/login?a={HttpUtility.UrlEncode(tokenString)}&c=doofen&t={DateTimeOffset.Now.ToUnixTimeSeconds()}";
- return Ok(new {code=200,url });
- }
- return Ok(new { code = 400 });
- }
- }
-
- }
|