消防培训系统服务器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

513 lines
20 KiB

2 years ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AX.FireTrainingSys.DTOs;
using AX.FireTrainingSys.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Mapster;
namespace AX.FireTrainingSys.Controllers.V1
{
/// <summary>
/// 课件库控制器。
/// </summary>
[Produces("application/json")]
[Route("api/[controller]")]
[ApiVersion("1.0")]
//[Authorize(Roles = "Profile")]
[ApiController]
public class CoursewaresController : ControllerBase
{
private readonly DriveDbContext dbContext;
public CoursewaresController(DriveDbContext dbContext)
{
this.dbContext = dbContext;
}
/// <summary>
/// 获得课件列表。
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status200OK)]
[HttpGet]
public async Task<ActionResult<Page<CoursewareInfo>>> Get([FromQuery] CoursewareQueryOptions options)
{
if (options.PageNumber == null)
options.PageNumber = 1;
if (options.PageSize == null)
options.PageSize = 10;
var username = HttpContext.User.FindFirstValue(JwtClaimTypes.Subject);
var queryable = dbContext.Coursewares
.Include(e => e.User)
.Include(e => e.BuildingTypes)
.AsNoTracking();
if (options.Others != null)
queryable = queryable.Where(e => options.Others.Value ? e.UserId != username : e.UserId == username);
if (options.IsPublic != null)
queryable = queryable.Where(e => e.IsPublic == options.IsPublic.Value);
if (options.Name != null)
queryable = queryable.Where(e => e.Name.Contains(options.Name));
if (options.ModifiedTime != null)
{
var modifiedTime = options.ModifiedTime.Value.UtcDateTime;
queryable = queryable.Where(e => e.ModifiedTime >= modifiedTime);
}
if (options.BuildingType != null)
queryable = queryable.Where(e => e.BuildingTypes.Any(c => c.BuildingTypeId == options.BuildingType));
if (!string.IsNullOrEmpty(options.CompanyName))
queryable = queryable.Where(e => e.CompanyName.Contains(options.CompanyName));
var count = await queryable.CountAsync();
queryable = queryable.OrderByDescending(e => e.ModifiedTime);
if (options.PageNumber > 1)
queryable = queryable.Skip((options.PageNumber.Value - 1) * options.PageSize.Value - 1);
queryable = queryable.Take(options.PageSize.Value);
var list = await queryable.Select(e => e.ToDTO())
.ToListAsync();
var result = new Page<CoursewareInfo>
{
PageNumber = (int)options.PageNumber,
PageSize = (int)options.PageSize,
TotalPages = (int)Math.Ceiling((double)count / (int)options.PageSize),
TotalCount = count,
Items = list
};
return Ok(result);
}
/// <summary>
/// 新建一个课件。
/// </summary>
/// <param name="companyName">单位/场景名称</param>
/// <param name="info"></param>
/// <returns></returns>
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status201Created)]
[HttpPost]
public async Task<ActionResult<CoursewareInfo>> Post([FromQuery] string companyName, [FromBody] CoursewareInfo info)
{
if (string.IsNullOrEmpty(info.Name))
return BadRequest(nameof(info.Name));
if (info.BuildingTypes == null || info.BuildingTypes.Length == 0)
return BadRequest(nameof(info.BuildingTypes));
var username = HttpContext.User.FindFirstValue(JwtClaimTypes.Subject);
var realname = HttpContext.User.FindFirstValue(JwtClaimTypes.Name);
using (var transaction = dbContext.Database.BeginTransaction())
{
var model = info.ToModel(username);
dbContext.Coursewares.Add(model);
var buildingTypes = info.Create(model.Id);
dbContext.Set<CoursewareBuildingType>().AddRange(buildingTypes);
await dbContext.SaveChangesAsync();
info.Id = model.Id;
info.Creator = realname;
info.ModifiedTime = model.ModifiedTime.ToLocalTime();
info.Referenced = false;
//从模板数据库中初始化课件数据
await dbContext.Database.ExecuteSqlInterpolatedAsync($@"
INSERT INTO BuildingAdjoins (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateBuildingAdjoins
WHERE CompanyName == {companyName};
INSERT INTO BuildingBasicInfos (CoursewareId, Content)
SELECT {info.Id}, Content FROM TemplateBuildingBasicInfos
WHERE CompanyName == {companyName};
INSERT INTO BuildingFeatures (CoursewareId, Content)
SELECT {info.Id}, Content FROM TemplateBuildingFeatures
WHERE CompanyName == {companyName};
INSERT INTO Exits (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateExits
WHERE CompanyName == {companyName};
INSERT INTO FireControlRooms (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateFireControlRooms
WHERE CompanyName == {companyName};
INSERT INTO FireLifts (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateFireLifts
WHERE CompanyName == {companyName};
INSERT INTO FireWaterMonitors (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateFireWaterMonitors
WHERE CompanyName == {companyName};
INSERT INTO FoamHydrants (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateFoamHydrants
WHERE CompanyName == {companyName};
INSERT INTO FoamPumpRooms (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateFoamPumpRooms
WHERE CompanyName == {companyName};
INSERT INTO ImageMarkers (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateImageMarkers
WHERE CompanyName == {companyName};
INSERT INTO ImportantLocations (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateImportantLocations
WHERE CompanyName == {companyName};
INSERT INTO MunicipalFireHydrants (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateMunicipalFireHydrants
WHERE CompanyName == {companyName};
INSERT INTO NoParkingAreas (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateNoParkingAreas
WHERE CompanyName == {companyName};
INSERT INTO OutdoorFireHydrants (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateOutdoorFireHydrants
WHERE CompanyName == {companyName};
INSERT INTO ProtectedStairways (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateProtectedStairways
WHERE CompanyName == {companyName};
INSERT INTO PumpRooms (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplatePumpRooms
WHERE CompanyName == {companyName};
INSERT INTO SiameseConnections (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateSiameseConnections
WHERE CompanyName == {companyName};
INSERT INTO StorageTanks (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateStorageTanks
WHERE CompanyName == {companyName};
INSERT INTO WaterTanks (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM TemplateWaterTanks
WHERE CompanyName == {companyName};
INSERT INTO Organizations(CoursewareId, Id, Name, Level, [Order], X, Y, Z, ParentId)
SELECT {info.Id}, Id, Name, Level, [Order], X, Y, Z, ParentId FROM TemplateOrganizations;
INSERT INTO FireForces(CoursewareId, Id, Type, Content, OrganizationId)
SELECT {info.Id}, Id, Type, Content, OrganizationId FROM TemplateFireForces;
");
transaction.Commit();
return CreatedAtAction(nameof(Post), info);
}
}
/// <summary>
/// 另存为一个课件。
/// </summary>
/// <param name="coursewareId">课件编号</param>
/// <returns></returns>
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status201Created)]
[HttpPost("[action]")]
public async Task<ActionResult<CoursewareInfo>> SaveAs([FromQuery] string coursewareId)
{
if (string.IsNullOrEmpty(coursewareId))
return BadRequest(coursewareId);
var m = await dbContext.Coursewares
.Include(e => e.BuildingTypes)
.Include(e => e.User)
.AsNoTracking()
.Where(e => e.Id == coursewareId)
.FirstOrDefaultAsync();
if (m == null)
return NotFound(coursewareId);
var info = m.ToDTO();
var username = HttpContext.User.FindFirstValue(JwtClaimTypes.Subject);
using (var transaction = dbContext.Database.BeginTransaction())
{
var model = info.ToModel(username);
dbContext.Coursewares.Add(model);
var buildingTypes = info.Create(model.Id);
dbContext.Set<CoursewareBuildingType>().AddRange(buildingTypes);
await dbContext.SaveChangesAsync();
info.Id = model.Id;
info.Creator = username;
info.ModifiedTime = model.ModifiedTime.ToLocalTime();
info.Referenced = false;
//从相关数据库中初始化课件数据
await dbContext.Database.ExecuteSqlInterpolatedAsync($@"
INSERT INTO BuildingAdjoins (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM BuildingAdjoins
WHERE CoursewareId == {coursewareId};
INSERT INTO BuildingBasicInfos (CoursewareId, Content)
SELECT {info.Id}, Content FROM BuildingBasicInfos
WHERE CoursewareId == {coursewareId};
INSERT INTO BuildingFeatures (CoursewareId, Content)
SELECT {info.Id}, Content FROM BuildingFeatures
WHERE CoursewareId == {coursewareId};
INSERT INTO Exits (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM Exits
WHERE CoursewareId == {coursewareId};
INSERT INTO FireControlRooms (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM FireControlRooms
WHERE CoursewareId == {coursewareId};
INSERT INTO FireLifts (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM FireLifts
WHERE CoursewareId == {coursewareId};
INSERT INTO FireWaterMonitors (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM FireWaterMonitors
WHERE CoursewareId == {coursewareId};
INSERT INTO FoamHydrants (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM FoamHydrants
WHERE CoursewareId == {coursewareId};
INSERT INTO FoamPumpRooms (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM FoamPumpRooms
WHERE CoursewareId == {coursewareId};
INSERT INTO ImageMarkers (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM ImageMarkers
WHERE CoursewareId == {coursewareId};
INSERT INTO ImportantLocations (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM ImportantLocations
WHERE CoursewareId == {coursewareId};
INSERT INTO MunicipalFireHydrants (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM MunicipalFireHydrants
WHERE CoursewareId == {coursewareId};
INSERT INTO NoParkingAreas (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM NoParkingAreas
WHERE CoursewareId == {coursewareId};
INSERT INTO OutdoorFireHydrants (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM OutdoorFireHydrants
WHERE CoursewareId == {coursewareId};
INSERT INTO ProtectedStairways (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM ProtectedStairways
WHERE CoursewareId == {coursewareId};
INSERT INTO PumpRooms (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM PumpRooms
WHERE CoursewareId == {coursewareId};
INSERT INTO SiameseConnections (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM SiameseConnections
WHERE CoursewareId == {coursewareId};
INSERT INTO StorageTanks (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM StorageTanks
WHERE CoursewareId == {coursewareId};
INSERT INTO WaterTanks (CoursewareId, Id, Content)
SELECT {info.Id}, Id, Content FROM WaterTanks
WHERE CoursewareId == {coursewareId};
INSERT INTO Organizations(CoursewareId, Id, Name, Level, [Order], X, Y, Z, ParentId)
SELECT {info.Id}, Id, Name, Level, [Order], X, Y, Z, ParentId FROM Organizations
WHERE CoursewareId == {coursewareId};
INSERT INTO FireForces(CoursewareId, Id, Type, Content, OrganizationId)
SELECT {info.Id}, Id, Type, Content, OrganizationId FROM FireForces
WHERE CoursewareId == {coursewareId};
");
transaction.Commit();
return CreatedAtAction(nameof(Post), info);
}
}
/// <summary>
/// 修改指定的课件信息。
/// </summary>
/// <param name="id"></param>
/// <param name="info"></param>
/// <returns></returns>
//[ProducesResponseType(ErrorCodes.E620)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[HttpPut("{id}")]
public async Task<Microsoft.AspNetCore.Mvc.ActionResult> Put(string id, [FromBody] CoursewareInfo info)
{
if (id != info.Id)
return BadRequest(id);
var username = HttpContext.User.FindFirstValue(JwtClaimTypes.Subject);
var model = await dbContext.Coursewares
.Include(e => e.BuildingTypes)
.FirstOrDefaultAsync(e => e.Id == id);
if (model == null)
return NotFound();
// 不能修改他人课件
if (model.UserId != username)
return Forbid();
// 不能撤销已被引用的公开课件
if (model.IsPublic &&
model.Referenced > 0 &&
info.IsPublic != null &&
info.IsPublic == false)
return this.ErrorCode(ErrorCodes.E620);
info.MapTo(model);
var currItems = model.BuildingTypes;
var newItems = info.Create(model.Id);
var removedItems = currItems.Except(newItems);
var addedItems = newItems.Except(currItems);
dbContext.Set<CoursewareBuildingType>().RemoveRange(removedItems);
dbContext.Set<CoursewareBuildingType>().AddRange(addedItems);
await dbContext.SaveChangesAsync();
return NoContent();
}
/// <summary>
/// 删除指定的课件信息。
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
//[ProducesResponseType(ErrorCodes.E621)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[HttpDelete("{id}")]
public async Task<Microsoft.AspNetCore.Mvc.ActionResult> Delete(string id)
{
var username = HttpContext.User.FindFirstValue(JwtClaimTypes.Subject);
var model = await dbContext.Coursewares.FindAsync(id);
if (model == null)
return NotFound();
// 不能删除他人课件
if (model.UserId != username)
return Forbid();
// 不能删除已被引用的公开课件
if (model.IsPublic &&
model.Referenced > 0)
return this.ErrorCode(ErrorCodes.E621);
model.Deleted = true;
model.Name = model.Name + "-" + ObjectId.NewId().ToString();
await dbContext.SaveChangesAsync();
return NoContent();
}
}
internal static class CoursewareExtensions
{
public static Courseware ToModel(this CoursewareInfo dto, string creator)
{
var model = dto.Adapt<Courseware>();
model.UserId = creator;
return model;
}
public static CoursewareInfo ToDTO(this Courseware model)
{
var buildingTypes = new int[model.BuildingTypes.Count];
var i = 0;
foreach (var type in model.BuildingTypes)
buildingTypes[i++] = type.BuildingTypeId;
var dto = model.Adapt<CoursewareInfo>();
dto.BuildingTypes = buildingTypes;
return dto;
}
public static void MapTo(this CoursewareInfo dto, Courseware model)
{
dto.Adapt(model);
model.ModifiedTime = DateTime.UtcNow;
}
public static IEnumerable<CoursewareBuildingType> Create(this CoursewareInfo dto, string id)
{
var buildingTypes = new List<CoursewareBuildingType>(dto.BuildingTypes.Length);
for (var i = 0; i < dto.BuildingTypes.Length; ++i)
{
var buildingType = new CoursewareBuildingType
{
CoursewareId = id,
BuildingTypeId = dto.BuildingTypes[i]
};
buildingTypes.Add(buildingType);
}
return buildingTypes;
}
}
}