VolumeController.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. using Azure;
  2. using Azure.Cosmos;
  3. using Microsoft.AspNetCore.Http;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.Extensions.Options;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Text.Json;
  11. using System.Threading.Tasks;
  12. using TEAMModelOS.Models;
  13. using TEAMModelOS.SDK.DI;
  14. using TEAMModelOS.SDK.Extension;
  15. using TEAMModelOS.SDK;
  16. using TEAMModelOS.SDK.Models;
  17. using TEAMModelOS.SDK.Models.Cosmos;
  18. using TEAMModelOS.SDK.Models.Cosmos.Common;
  19. using HTEXLib.COMM.Helpers;
  20. using Microsoft.AspNetCore.Authorization;
  21. using TEAMModelOS.Filter;
  22. using Microsoft.Extensions.Hosting;
  23. using OpenXmlPowerTools;
  24. using Microsoft.AspNetCore.Hosting;
  25. using Microsoft.Extensions.Configuration;
  26. using TEAMModelOS.SDK.Models.Dtos;
  27. namespace TEAMModelOS.Controllers
  28. {
  29. [ProducesResponseType(StatusCodes.Status200OK)]
  30. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  31. //
  32. [Route("common/volume")]
  33. [ApiController]
  34. public class VolumeController : ControllerBase
  35. {
  36. private readonly AzureCosmosFactory _azureCosmos;
  37. private readonly SnowflakeId _snowflakeId;
  38. private readonly DingDing _dingDing;
  39. private readonly Option _option;
  40. private readonly CoreAPIHttpService _coreAPIHttpService;
  41. private readonly IWebHostEnvironment _environment;
  42. private readonly IConfiguration _configuration;
  43. public VolumeController(IConfiguration configuration, CoreAPIHttpService coreAPIHttpServic, IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option)
  44. {
  45. _azureCosmos = azureCosmos;
  46. _snowflakeId = snowflakeId;
  47. _dingDing = dingDing;
  48. _option = option?.Value;
  49. _environment = environment;
  50. _coreAPIHttpService = coreAPIHttpServic;
  51. _configuration = configuration;
  52. }
  53. /*
  54. {
  55. "id": "册别id",
  56. "code": "学校编码/教师编码",
  57. "scope": "school/private"
  58. }
  59. */
  60. /// <summary>
  61. /// 删除册别
  62. /// </summary>
  63. /// <param name="request"></param>
  64. /// <returns></returns>
  65. [ProducesDefaultResponseType]
  66. //[AuthToken(Roles = "teacher")]
  67. [HttpPost("delete")]
  68. [Authorize(Roles = "IES")]
  69. [AuthToken(Roles = "teacher,admin")]
  70. public async Task<IActionResult> Delete(JsonElement request)
  71. {
  72. try
  73. {
  74. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  75. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  76. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  77. var client = _azureCosmos.GetCosmosClient();
  78. string sql = $"select value(c) from c where c.volumeId='{id}'";
  79. List<Syllabus> syllabus = new List<Syllabus>();
  80. if (scope.ToString().Equals("school"))
  81. {
  82. var response = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Volume-{code}"));
  83. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Syllabus>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{code}") })) {
  84. syllabus.Add(item);
  85. }
  86. if (syllabus.IsNotEmpty())
  87. {
  88. foreach (var s in syllabus) {
  89. if (s.auth.IsNotEmpty()) {
  90. foreach (var a in s.auth) {
  91. try {
  92. Share share = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Share>(s.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
  93. share.agree = -1;
  94. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Share>(share, s.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
  95. } catch (Exception ex) {
  96. ///仅用于处理查不到该数据的问题
  97. }
  98. }
  99. }
  100. }
  101. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemsStreamAsync(syllabus.Select(x => x.id).ToList(), $"Syllabus-{code}");
  102. }
  103. return Ok(new { code = response.Status });
  104. }
  105. else
  106. {
  107. var response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Volume-{code}"));
  108. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Syllabus>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{code}") }))
  109. {
  110. syllabus.Add(item);
  111. }
  112. if (syllabus.IsNotEmpty())
  113. {
  114. foreach (var s in syllabus)
  115. {
  116. if (s.auth.IsNotEmpty())
  117. {
  118. foreach (var a in s.auth)
  119. {
  120. try
  121. {
  122. Share share = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Share>(s.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
  123. share.agree = -1;
  124. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Share>(share, s.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
  125. }
  126. catch (Exception ex)
  127. {
  128. ///仅用于处理查不到该数据的问题
  129. }
  130. }
  131. }
  132. }
  133. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemsStreamAsync(syllabus.Select(x => x.id).ToList(), $"Syllabus-{code}");
  134. }
  135. return Ok(new { code = response.Status });
  136. }
  137. }
  138. catch (Exception ex)
  139. {
  140. await _dingDing.SendBotMsg($"OS,{_option.Location},VolumeController:Delete\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  141. return BadRequest();
  142. }
  143. }
  144. /*
  145. {
  146. "periodId": "学段id",
  147. "subjectId": "科目id",//
  148. "status": 1,//状态
  149. "code": "学校编码或者tmdid",
  150. "scope": "school/private" 如果是私人课纲 则学段科目id可以为空
  151. }
  152. */
  153. /// <summary>
  154. /// 查找册别
  155. /// </summary>
  156. /// <param name="request"></param>
  157. /// <returns></returns>
  158. [ProducesDefaultResponseType]
  159. //[AuthToken(Roles = "teacher")]
  160. [HttpPost("find")]
  161. [Authorize(Roles = "IES")]
  162. [AuthToken(Roles = "teacher,admin,student")]
  163. public async Task<IActionResult> Find(JsonElement request) {
  164. try {
  165. List<Volume> volumes = new List<Volume>();
  166. request.TryGetProperty("periodId", out JsonElement periodCode);
  167. request.TryGetProperty("subjectId", out JsonElement subjectCode);
  168. request.TryGetProperty("status", out JsonElement status);
  169. if (request.TryGetProperty("code", out JsonElement code))
  170. {
  171. request.TryGetProperty("scope", out JsonElement scope);
  172. //私有课纲
  173. if (scope.GetString().Equals("private"))
  174. {
  175. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Volume>(queryText: $"select value(c) from c where c.status = {status}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Volume-{code}") }))
  176. {
  177. volumes.Add(item);
  178. }
  179. }
  180. else if (scope.GetString().Equals("school"))
  181. {
  182. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Volume>(queryText: $"select value(c) from c where c.status = {status} and c.periodId = '{periodCode}' and c.subjectId = '{subjectCode}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Volume-{code}") }))
  183. {
  184. volumes.Add(item);
  185. }
  186. }
  187. }
  188. else { return BadRequest(); };
  189. volumes= volumes.OrderBy(x => x.order).ToList();
  190. return Ok(new { volumes });
  191. } catch (Exception ex) {
  192. await _dingDing.SendBotMsg($"OS,{_option.Location},VolumeController:find\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  193. return BadRequest();
  194. }
  195. }
  196. //{"code":"hbcn/1528783259","scope":"school/private","update":"order","data":[{"key":"1","value":1}]}
  197. /// <summary>
  198. /// 批量更新相同的属性。
  199. /// </summary>
  200. /// <param name="request"></param>
  201. /// <returns></returns>
  202. [ProducesDefaultResponseType]
  203. //[AuthToken(Roles = "teacher")]
  204. [HttpPost("update-same-property")]
  205. [Authorize(Roles = "IES")]
  206. [AuthToken(Roles = "teacher,admin")]
  207. public async Task<IActionResult> UpsertSameProperty(JsonElement request) {
  208. var client = _azureCosmos.GetCosmosClient();
  209. request.TryGetProperty("code", out JsonElement _code);
  210. request.TryGetProperty("scope", out JsonElement _scope);
  211. request.TryGetProperty("update", out JsonElement _update);
  212. request.TryGetProperty("data", out JsonElement _data);
  213. string tbname = $"{_scope}".Equals("school") ? "School" : "Teacher";
  214. List<Dictionary<string, object>> dicts = _data.ToObject<List<Dictionary<string, object>>>();
  215. foreach (var dict in dicts)
  216. {
  217. try
  218. {
  219. Volume volume = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<Volume>($"{dict["key"]}", new PartitionKey($"Volume-{_code}"));
  220. bool modify = false;
  221. switch (true)
  222. {
  223. //修改排序
  224. case bool when $"{_update}".Equals("order", StringComparison.OrdinalIgnoreCase):
  225. if (int.TryParse($"{dict["value"]}", out int order))
  226. {
  227. volume.order = order;
  228. modify= true;
  229. }
  230. break;
  231. }
  232. if (modify) {
  233. await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<Volume>(volume, volume.id, new PartitionKey($"Volume-{_code}"));
  234. }
  235. }
  236. catch (Exception ex)
  237. {
  238. continue;
  239. }
  240. }
  241. return Ok(new { status=200});
  242. }
  243. /*
  244. {
  245. "id": "册别id",
  246. "code": "学校编码或教师id",
  247. "periodId": "学段id",
  248. "subjectId": "学科id",
  249. "gradeId": "年级id",
  250. "semesterId": "学期id",
  251. "status": 1,
  252. "name": "册别名",
  253. "creatorId": "创建者id",
  254. "school": "学校编码",
  255. "scope": "school|private"
  256. }
  257. */
  258. /// <summary>
  259. /// 新增册别
  260. /// </summary>
  261. /// <param name="request"></param>
  262. /// <returns></returns>
  263. [ProducesDefaultResponseType]
  264. //[AuthToken(Roles = "teacher")]
  265. [HttpPost("upsert")]
  266. [Authorize(Roles = "IES")]
  267. [AuthToken(Roles = "teacher,admin")]
  268. public async Task<IActionResult> Upsert(Volume request) {
  269. //var client = _azureCosmos.GetCosmosClient();
  270. //if (request.editors != null && request.editors.Count > 5)
  271. //{
  272. // return BadRequest("共编人数大于5人!");
  273. // // throw new BizException("共编人数大于5人!");
  274. //}
  275. request.pk = "Volume";
  276. request.ttl = -1;
  277. request.code = "Volume-" + request.code;
  278. // 检查册别条件相同的是否存在
  279. List<string> coeditIds = new List<string>();
  280. string code = "Volume-";
  281. if (request.scope.Equals("private"))
  282. {
  283. code = $"Volume-{request.creatorId}";
  284. }
  285. else if (request.scope.Equals("school"))
  286. {
  287. code = $"Volume-{request.school}";
  288. }
  289. request.createTime= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  290. request.code = code;
  291. ///表示更新
  292. if (!string.IsNullOrEmpty(request.id))
  293. {
  294. try {
  295. if (request.scope.Equals("school"))
  296. {
  297. Volume volume= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Volume>(request.id, new Azure.Cosmos.PartitionKey(request.code));
  298. var exceptIds= volume.auth.Select(x => x.tmdid).Except(request.auth.Select(y => y.tmdid));
  299. if (exceptIds.Any()) {
  300. coeditIds.AddRange(exceptIds);
  301. }
  302. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Volume>(request, request.id, new Azure.Cosmos.PartitionKey(request.code));
  303. }
  304. else if (request.scope.Equals("private")) {
  305. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Volume>(request, request.id, new Azure.Cosmos.PartitionKey(request.code));
  306. }
  307. }
  308. catch (Exception ex) {
  309. return BadRequest(new { error = ResponseCode.FAILED });
  310. }
  311. }
  312. //表示新增,则需要检查是否重复
  313. else {
  314. try
  315. {
  316. StringBuilder sql = new StringBuilder("select value(c) from c where c.status = 1 ");
  317. //私人课纲 只检查是否重名
  318. if (request.scope.Equals("private"))
  319. {
  320. sql.Append($" and c.name = '{request.name}' ");
  321. List<Volume> volumes = new List<Volume>();
  322. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher")
  323. .GetItemQueryIterator<Volume>(queryText: sql.ToString(), requestOptions: new Azure.Cosmos.QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey(request.code) }))
  324. {
  325. volumes.Add(item);
  326. }
  327. if (volumes.Count > 0)
  328. {
  329. return Ok(new { error = ResponseCode.DATA_EXIST });
  330. }
  331. }
  332. //学校课纲检查 学段 科目 年级 学期
  333. else if (request.scope.Equals("school")
  334. && !string.IsNullOrEmpty(request.periodId)
  335. && !string.IsNullOrEmpty(request.subjectId)
  336. && request.gradeId>=0
  337. && !string.IsNullOrEmpty(request.semesterId))
  338. {
  339. sql.Append($" and c.periodId = '{request.periodId}' and c.subjectId = '{request.subjectId}'" +
  340. $" and c.gradeId = {request.gradeId} and c.semesterId = '{request.semesterId}' and c.name = '{request.name}' ");
  341. List<Volume> volumes = new List<Volume>();
  342. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School")
  343. .GetItemQueryIterator<Volume>(queryText: sql.ToString(), requestOptions: new Azure.Cosmos.QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey(request.code) })) {
  344. volumes.Add(item);
  345. }
  346. if (volumes.Count>0)
  347. {
  348. return Ok(new { error = ResponseCode.DATA_EXIST });
  349. }
  350. }
  351. else {
  352. return BadRequest(new { error = ResponseCode.PARAMS_ERROR });
  353. }
  354. request.id = System.Guid.NewGuid().ToString();
  355. if (request.scope.Equals("private"))
  356. {
  357. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync(request, new PartitionKey(request.code));
  358. }
  359. else {
  360. coeditIds = request.auth.Select(x => x.tmdid).ToList() ;
  361. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(request, new PartitionKey(request.code));
  362. }
  363. }
  364. catch (Exception ex)
  365. {
  366. await _dingDing.SendBotMsg($"OS,{_option.Location},VolumeController:Upsert\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  367. }
  368. }
  369. ///处理更新 分享及共编的数据
  370. //if (request.auth.IsNotEmpty()) {
  371. // long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  372. // foreach (var au in request.auth) {
  373. // var share= new Share
  374. // {
  375. // id = request.id,
  376. // code = $"Share-{au.tmdid}",
  377. // pk = "Share",
  378. // ttl = -1,
  379. // scode=request.code,
  380. // issuer=request.creatorId,
  381. // createTime= now,
  382. // school=request.school,
  383. // scope=request.scope
  384. // };
  385. // await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync(share, new PartitionKey($"{share.code}"));
  386. // }
  387. //}
  388. if (coeditIds.IsNotEmpty()) {
  389. School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(request.school, new Azure.Cosmos.PartitionKey("Base"));
  390. string sql = $"select c.id, c.name ,c.lang as code from c where c.id in ({string.Join(",", coeditIds.Select(x => $"'{x}'"))})";
  391. List<IdNameCode> idNameCodes = new List<IdNameCode>();
  392. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  393. .GetItemQueryIterator<IdNameCode>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  394. {
  395. idNameCodes.Add(item);
  396. }
  397. _coreAPIHttpService.PushNotify(idNameCodes, "coedit_volume", Constant.NotifyType_IES5_Contect,
  398. new Dictionary<string, object> { { "tmdname", request.creatorName }, { "tmdid", request.creatorId },{ "schoolName",school.name }, { "schoolId",school.id }, { "volumeId", request.id }, { "volumeName", request.name } },
  399. _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
  400. }
  401. return Ok(request);
  402. }
  403. }
  404. }