VolumeController.cs 21 KB

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