Files
Docker/CloudBuilder/CloudBuilder.Master.Service/PublishVideoService.auto.cs
T
2026-10-21 20:50:55 +08:00

481 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using CloudBuilder.Core.DatabaseAccessor;
using CloudBuilder.Core.DatabaseAccessor.Entity;
using CloudBuilder.Core.Policy;
using CloudBuilder.Core.Service;
using CloudBuilder.Master.Data;
using CloudBuilder.Master.Entity;
using CloudBuilder.Master.Policy;
using CloudBuilder.Master.SearchCriteria;
using CloudBuilder.Security.Entity;
using CloudBuilder.Security.Policy;
using CloudBuilder.Security.Service;
using CloudBuilder.Security.Utility;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
namespace CloudBuilder.Master.Service
{
public class PublishVideoService : IPublishVideoService
{
private readonly IApplicationService service;
private IRepository<PublishVideoEntity> repository;
public PublishVideoService(IApplicationService service)
{
this.service = service;
repository = service.GetRepository<IRepository<PublishVideoEntity>>();
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Find)]
public PublishVideoData FindByKey(string key)
{
PublishVideoData data = new PublishVideoData();
if (string.IsNullOrEmpty(key)) return data;
PublishVideoEntity publish = repository.DetachedEntities.Where(x => x.PublishName == key).FirstOrDefault();
if (publish == null) return data;
IRepository<PublishVideoFamilyGroupEntity> repositoryPublishVideoFamilyGroup = repository.GetRepository<IRepository<PublishVideoFamilyGroupEntity>>();
IRepository<FamilyGroupEntity> repositoryFamilyGroup = repository.GetRepository<IRepository<FamilyGroupEntity>>();
IQueryable<PublishVideoFamilyGroupDisplayData>? q = from e in repositoryPublishVideoFamilyGroup.DetachedEntities
join fg in repositoryFamilyGroup.DetachedEntities on e.FamilyName equals fg.FamilyName
where e.PublishName == key
select new PublishVideoFamilyGroupDisplayData(fg)
{
CreatedBy = e.CreatedBy,
CreatedDatetime = e.CreatedDatetime,
UpdatedBy = e.UpdatedBy,
UpdatedDatetime = e.UpdatedDatetime,
PublishName = e.PublishName,
};
data.FamilyGroups = q.ToArray();
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
//归属与群组身份:所有者全权;群管理员可删/改信息;群成员仅可改明细
data.IsOwner = publish.OwnerName == service.UserId;
data.IsMember = data.IsOwner;
data.IsManager = data.IsOwner;
if (!data.IsOwner && data.FamilyGroups.Length > 0)
{
string[] familyNames = data.FamilyGroups.Select(x => x.FamilyName).ToArray();
FamilyGroupManagerEntity[] mine = repositoryFamilyGroupManager.DetachedEntities
.Where(x => x.UserName == service.UserId && x.ValidIndc == YesNoPolicy.YES && familyNames.Contains(x.FamilyName))
.ToArray();
data.IsMember = mine.Length > 0;
data.IsManager = mine.Any(x => x.ManagerIndc == YesNoPolicy.YES);
}
if (!data.IsOwner && !YesNoPolicy.IsYes(publish.OpenIndc) && !data.IsMember)
{
throw new ValidatedException("没有权限.");
}
data.PublishVideo = publish;
IRepository<PublishVideoDetailEntity> repositoryPublishVideoDetail = repository.GetRepository<IRepository<PublishVideoDetailEntity>>();
data.Details = repositoryPublishVideoDetail.DetachedEntities.Where(x => x.PublishName == publish.PublishName).OrderBy(x => x.OrderBy).Select(x => new PublishVideoDetailDisplayData(x)).ToArray();
if (data.Details != null && data.Details.Length > 0)
{
var webRootPath = service.Configuration[ServiceSettingsPolicy.RequestPath];
var phy = service.Configuration[ServiceSettingsPolicy.PhysicalFileDirectory];
var scale = ServiceSettingsPolicy.GetDmsFileScaleDirectory(service).Replace(phy, "");
IRepository<DmsFileEntity> repositoryDmsFile = repository.GetRepository<IRepository<DmsFileEntity>>();
foreach (var item in data.Details)
{
if (!string.IsNullOrEmpty(item.Url) && FileTypePolicy.GetType(item.Url!) == FileTypePolicy.VIDEO)
{
var upload = ServiceSettingsPolicy.GetDmsFileUploadDirectory(service).Replace(phy, "");
//暂时不支持转码
DmsFileEntity dmsFileEntity = repositoryDmsFile.DetachedEntities.Where(x => x.OrderKey == item.Url).FirstOrDefault();
// 文件可能由群成员从自己的网盘里挑:按 dms_file 的真实归属目录拼,查不到才回落明细创建人
string owner = !string.IsNullOrEmpty(dmsFileEntity?.CreatedBy) ? dmsFileEntity.CreatedBy : item.CreatedBy;
item.FormattedPic = FileTypePolicy.PackPicUrl(service, owner, item.Url);
item.FormattedUrl = FileTypePolicy.PackUrl(service, owner, item.Url);
item.FormattedM3u8 = FileTypePolicy.PackM3u8Url(service, owner, item.Url);
}
}
}
return data;
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Find)]
public PublishVideoResultData FindBySearchCriteria(PublishVideoSearchCriteria criteria)
{
PublishVideoResultData data = new PublishVideoResultData();
PublishVideoEntity[] list = null;
Int64 count = 0;
string sqlWhere = null;
if (criteria.Filter != null && criteria.Filter.Length > 0)
{
sqlWhere = SearchFilter.ComposeWhereClause(criteria.Filter);
}
sqlWhere = sqlWhere + string.Format(" and ({0} ='{1}' or {2} ='{3}') ",
PublishVideoEntity.DB_OWNER_NAME, service.UserId,
PublishVideoEntity.DB_OPEN_INDC, criteria.IsModal ? service.UserId : YesNoPolicy.YES);
PublishVideoEntity entity = PublishVideoEntity.GetInstance(repository.GetDbContext().Database.ProviderName);
string sql = entity.GetSelectTopFrom(criteria.limit, criteria.page, criteria.orderby.StringToDbField(), criteria.orderbytag, sqlWhere);
string err = null;
try
{
list = repository.FromSql(sql).ToArray();
}
catch (System.Exception ex)
{
err = ex.Message;
}
if (list != null && list.Length > 0)
{
sql = entity.GetSelectCountFrom(sqlWhere);
count = Convert.ToInt64(repository.ExecuteScalar(sql));
}
data.Limit = criteria.limit;
data.Page = criteria.page;
data.Datas = list;
data.Total = count;
//data.Sql = sql;
data.ErrorMessage = err;
return data;
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Find)]
public PublishVideoData FindPublishVideoDefault()
{
PublishVideoEntity publish = repository.DetachedEntities.Where(x => x.OwnerName == service.UserId && x.DefaultIndc == YesNoPolicy.YES).FirstOrDefault();
if (publish == null) return null;
return FindByKey(publish.PublishName);
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Print)]
public dynamic PrintBySearchCriteria(PublishVideoSearchCriteria criteria)
{
throw new NotImplementedException();
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Insert)]
[UnitOfWork]
public PublishVideoData Insert(PublishVideoData data)
{
PublishVideoEntity photoPublish = repository.DetachedEntities.Where(x => x.PublishLocalName == data.PublishVideo.PublishLocalName).FirstOrDefault();
if (photoPublish != null)
{
throw new ValidatedException($"[{photoPublish.PublishLocalName}]已发布.");
}
Validate(data.PublishVideo);
if (data.PublishVideo.DefaultIndc == YesNoPolicy.YES)
{
CancelDefaultIndc(null);
}
photoPublish = new PublishVideoEntity();
ObjectCopyHelper.Copy(data.PublishVideo, photoPublish);
ISecurityGeneratorNumberService securityGeneratorNumberService = service.ServiceProvider.GetService<ISecurityGeneratorNumberService>()!;
photoPublish.PublishName = securityGeneratorNumberService.GetNo(MasterPrefixPolicy.AUDIO_PUBLISH, MasterPrefixPolicy.AUDIO_PUBLISH_PUBLISH_NAME, "AP", YesNoPolicy.YES, "yymmdd00000");
photoPublish.OwnerName = service.UserId;
repository.InsertNow(photoPublish);
SavePublishVideoFamilyGroup(photoPublish.PublishName, data.FamilyGroups);
return FindByKey(photoPublish.PublishName);
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Update)]
[UnitOfWork]
public PublishVideoData Update(PublishVideoData data)
{
//归属校验:所有者可全改;公开群组管理员可改信息/群组;普通群成员只能改明细
PublishVideoEntity original = repository.DetachedEntities.Where(x => x.PublishName == data.PublishVideo.PublishName).FirstOrDefault();
if (original == null)
{
throw new ValidatedException("记录不存在.");
}
bool isOwner = original.OwnerName == service.UserId;
bool isManager = false;
bool isMember = false;
if (!isOwner)
{
IRepository<PublishVideoFamilyGroupEntity> repositoryPublishVideoFamilyGroup = repository.GetRepository<IRepository<PublishVideoFamilyGroupEntity>>();
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
string[] familyNames = repositoryPublishVideoFamilyGroup.DetachedEntities
.Where(x => x.PublishName == original.PublishName)
.Select(x => x.FamilyName)
.ToArray();
if (familyNames.Length == 0)
{
throw new ValidatedException("没有权限.");
}
FamilyGroupManagerEntity[] mine = repositoryFamilyGroupManager.DetachedEntities
.Where(x => x.UserName == service.UserId && x.ValidIndc == YesNoPolicy.YES && familyNames.Contains(x.FamilyName))
.ToArray();
isMember = mine.Length > 0;
isManager = mine.Any(x => x.ManagerIndc == YesNoPolicy.YES);
if (!isMember)
{
throw new ValidatedException("没有权限.");
}
}
//非所有者保留归属与建单信息,防客户端伪造
data.PublishVideo.OwnerName = original.OwnerName;
data.PublishVideo.CreatedBy = original.CreatedBy;
data.PublishVideo.CreatedDatetime = original.CreatedDatetime;
if (!isOwner && !isManager)
{
//非所有者且非管理员(普通群成员)只能改明细:专辑展示字段一律以库中为准
data.PublishVideo.PublishLocalName = original.PublishLocalName;
data.PublishVideo.Notice = original.Notice;
data.PublishVideo.OpenIndc = original.OpenIndc;
data.PublishVideo.ExpireDatetime = original.ExpireDatetime;
data.PublishVideo.OrderBy = original.OrderBy;
}
if (!isOwner)
{
//默认专辑是所有者个人偏好,群管理员也不能改
data.PublishVideo.DefaultIndc = original.DefaultIndc;
}
ValidateHelper.Validate(service, data.PublishVideo, PublishVideoEntity.DB_NAME_PUBLISH_VIDEO);
if (isOwner && data.PublishVideo.DefaultIndc == YesNoPolicy.YES)
{
CancelDefaultIndc(data.PublishVideo.PublishName);
}
PublishVideoEntity publishEntity = new PublishVideoEntity();
ObjectCopyHelper.Copy(data.PublishVideo, publishEntity);
repository.UpdateNow(publishEntity);
//只有删除和更新,没有插入
SavePublishVideoDetails(publishEntity.PublishName, data.Details);
//群组增删只对所有者/群管理员开放;普通成员提交的 FamilyGroups 不落库
if (isOwner || isManager)
{
SavePublishVideoFamilyGroup(publishEntity.PublishName, data.FamilyGroups);
}
return FindByKey(publishEntity.PublishName);
}
/// <summary>当前登录人是否为该专辑任一公开群组的管理员(正式成员且 ManagerIndc=Y)</summary>
private bool IsGroupManagerOfPublish(string publishName)
{
IRepository<PublishVideoFamilyGroupEntity> repositoryFamilyGroup = repository.GetRepository<IRepository<PublishVideoFamilyGroupEntity>>();
IRepository<FamilyGroupManagerEntity> repositoryFamilyGroupManager = repository.GetRepository<IRepository<FamilyGroupManagerEntity>>();
string[] familyNames = repositoryFamilyGroup.DetachedEntities
.Where(x => x.PublishName == publishName)
.Select(x => x.FamilyName)
.ToArray();
if (familyNames.Length == 0)
{
return false;
}
return repositoryFamilyGroupManager.DetachedEntities
.Any(x => x.UserName == service.UserId && x.ValidIndc == YesNoPolicy.YES && x.ManagerIndc == YesNoPolicy.YES && familyNames.Contains(x.FamilyName));
}
private void SavePublishVideoDetails(string publishName, PublishVideoDetailEntity[] details)
{
if (details != null && details.Length > 0)
{
int i = 1;
foreach (PublishVideoDetailEntity dtl in details)
{
dtl.OrderBy = i++;
}
}
IRepository<PublishVideoDetailEntity> repositoryPublishVideoDetail = repository.GetRepository<IRepository<PublishVideoDetailEntity>>();
PublishVideoDetailEntity[] olds = repositoryPublishVideoDetail.Entities.Where(x => x.PublishName == publishName).ToArray();
if (olds != null && olds.Length > 0)
{
//存在更新,不存在删除
foreach (PublishVideoDetailEntity old in olds)
{
if (details != null && details.Length > 0 && details.Where(x => x.DetailId == old.DetailId).Count() > 0)
{
PublishVideoDetailEntity dtl = details.Where(x => x.DetailId == old.DetailId).FirstOrDefault();
old.Title = dtl.Title;
old.Author = dtl.Author;
old.Pic = dtl.Pic;
old.Url = dtl.Url;
old.Lrc = dtl.Lrc;
old.OrderBy = dtl.OrderBy;
old.Notice = dtl.Notice;
repositoryPublishVideoDetail.UpdateNow(old);
}
else
{
repositoryPublishVideoDetail.DeleteNow(old);
}
}
}
}
private void Validate(PublishVideoEntity photoPublish)
{
List<SysTableSchemaViewEntity> sysTableSchemas = service.ServiceProvider.GetRequiredService<ISysTableSchemaViewService>().FindByTableName(PublishVideoEntity.DB_NAME_PUBLISH_VIDEO);
ValidateHelper.ValidateString(photoPublish, sysTableSchemas.ToArray());
}
private void SavePublishVideoFamilyGroup(string publishName, PublishVideoFamilyGroupEntity[] familyGroups)
{
IRepository<PublishVideoFamilyGroupEntity> repositoryPublishVideoFamilyGroup = repository.GetRepository<IRepository<PublishVideoFamilyGroupEntity>>();
PublishVideoFamilyGroupEntity[] olds = repositoryPublishVideoFamilyGroup.Entities.Where(x => x.PublishName == publishName).ToArray();
if (olds != null && olds.Length > 0)
{
//存在更新,不存在删除
foreach (PublishVideoFamilyGroupEntity old in olds)
{
if (familyGroups != null && familyGroups.Length > 0 && familyGroups.Where(x => x.FamilyName == old.FamilyName).Count() > 0)
{
//只有主键,无需更新
//repositoryPpf.UpdateNow(old);
}
else
{
repositoryPublishVideoFamilyGroup.DeleteNow(old);
}
}
}
if (familyGroups != null && familyGroups.Length > 0)
foreach (PublishVideoFamilyGroupEntity dto in familyGroups)
{
if (string.IsNullOrEmpty(dto.CreatedBy))
repositoryPublishVideoFamilyGroup.InsertNow(new PublishVideoFamilyGroupEntity()
{
PublishName = publishName,
FamilyName = dto.FamilyName,
});
}
}
public void CancelDefaultIndc(string publishLocalName)
{
PublishVideoEntity[] orgs = repository.DetachedEntities.Where(x => x.PublishName != publishLocalName && x.OwnerName == service.UserId && x.DefaultIndc == YesNoPolicy.YES).ToArray();
foreach (PublishVideoEntity org in orgs)
{
org.DefaultIndc = YesNoPolicy.NO;
}
if (orgs != null && orgs.Length > 0)
repository.UpdateNow(orgs);
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Delete)]
[UnitOfWork]
public void Delete(string key)
{
PublishVideoEntity publishEntity = repository.DetachedEntities.Where(x => x.PublishName == key).FirstOrDefault();
if (publishEntity == null)
{
throw new ValidatedException("记录不存在.");
}
//删除专辑:所有者或该专辑任一公开群组的管理员
if (publishEntity.OwnerName != service.UserId && !IsGroupManagerOfPublish(key))
{
throw new ValidatedException("没有权限.");
}
repository.DeleteNow(publishEntity);
IRepository<PublishVideoDetailEntity> repositoryDetail = repository.GetRepository<IRepository<PublishVideoDetailEntity>>();
PublishVideoDetailEntity[] detail = repositoryDetail.Entities.Where(x => x.PublishName == key).ToArray();
if (detail != null && detail.Length > 0)
{
foreach (PublishVideoDetailEntity dtl in detail)
{
repositoryDetail.DeleteNow(dtl);
}
}
IRepository<PublishVideoFamilyGroupEntity> repositoryFamilyGroup = repository.GetRepository<IRepository<PublishVideoFamilyGroupEntity>>();
PublishVideoFamilyGroupEntity[] groups = repositoryFamilyGroup.Entities.Where(x => x.PublishName == key).ToArray();
if (groups != null && groups.Length > 0)
{
foreach (PublishVideoFamilyGroupEntity gp in groups)
{
repositoryFamilyGroup.DeleteNow(gp);
}
}
}
[PermissionOperate(name: MasterPermissionPolicy.PublishVideo, operate: Operate.Insert)]
public void InsertPublishVideoDetail(PublishData publishData)
{
IRepository<DmsFileUploadViewEntity> repositoryDmsFile = repository.GetRepository<IRepository<DmsFileUploadViewEntity>>();
DmsFileUploadViewEntity dmsFile = repositoryDmsFile.DetachedEntities.Where(x => x.FileId == publishData.FileId).FirstOrDefault();
if (dmsFile == null) return;
if (!FileTypePolicy.IsVideo(dmsFile.OrderKey)) return;
InsertPublishVideoDetail(dmsFile, publishData.PublishName);
}
private void InsertPublishVideoDetail(DmsFileUploadViewEntity dmsFile, string publishName)
{
IRepository<PublishVideoDetailEntity> repositoryPublishVideoDetail = repository.GetRepository<IRepository<PublishVideoDetailEntity>>();
PublishVideoDetailEntity[] dtls = repositoryPublishVideoDetail.DetachedEntities.Where(x => x.PublishName == publishName).ToArray();
if (dtls != null && dtls.Where(x => x.Url == dmsFile.OrderKey).Count() > 0) return;
PublishVideoDetailEntity dtl = new PublishVideoDetailEntity();
dtl.PublishName = publishName;
string orgFileName = Path.GetFileNameWithoutExtension(dmsFile.OrgFileName);
string[] tts = orgFileName.Split('-');
dtl.Title = tts[0].Trim();
if (tts.Length > 1) dtl.Author = tts[1].Trim();
dtl.OwnerName = dmsFile.OwerId;
if (dtls != null && dtls.Length > 0)
dtl.OrderBy = dtls.Sum(x => x.OrderBy) + 1;
dtl.Url = dmsFile.OrderKey;
repositoryPublishVideoDetail.InsertNow(dtl);
}
}
}