using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using AutoMapper;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Infrastructure;
using Dpz.Core.Public.Entity;
namespace Dpz.Core.Public.ViewModel;
public class CommentViewModel : IHaveCustomMapping
{
public string Id { get; set; }
/// <summary>
/// 评论类型
/// </summary>
public CommentNode Node { get; set; }
/// <summary>
/// 关联
/// </summary>
public string Relation { get; set; }
/// <summary>
/// 回复时间
/// </summary>
public DateTime PublishTime { get; set; }
/// <summary>
/// 评论人
/// </summary>
[JsonConverter(typeof(CommenterConverter))]
public VmCommenter? Commenter { get; set; }
/// <summary>
/// 回复内容
/// </summary>
public string? CommentText { get; set; }
/// <summary>
/// 回复ID
/// </summary>
public List<string>? Replies { get; set; }
/// <summary>
/// 是否删除
/// </summary>
public bool? IsDelete { get; set; }
/// <summary>
/// 回复
/// </summary>
public List<CommentChildren>? Children { get; set; }
private IMapper _mapper = new Mapper(new MapperConfiguration(x =>
{
x.CreateMap<MembleCommenter, VmMemberCommenter>();
x.CreateMap<GuestCommenter, VmGuestCommenter>();
}));
public void CreateMappings(MapperConfigurationExpression cfg)
{
cfg.CreateMap<Comment, CommentViewModel>().ConvertUsing((entity, _) =>
{
if (entity.IsDelete == true)
{
entity.Commenter = new GuestCommenter
{
Email = "",
NickName = "该用户发言已被删除",
Site = ""
};
entity.CommentText = "该用户发言因某些原因已被删除";
}
var viewModel = new CommentViewModel
{
Id = entity.Id.ToString(),
Node = entity.Node,
Relation = entity.Relation,
PublishTime = entity.PublishTime.ToLocalTime(),
CommentText = entity.CommentText,
Replies = entity.Replies == null
? new List<string>()
: entity.Replies.Select(x => x.ToString()).ToList(),
IsDelete = entity.IsDelete,
Children = new List<CommentChildren>(),
Commenter = entity.Commenter switch
{
MembleCommenter membleCommenter => _mapper.Map<VmMemberCommenter>(membleCommenter),
GuestCommenter guestCommenter => _mapper.Map<VmGuestCommenter>(guestCommenter),
_ => null
}
};
return viewModel;
});
}
}
public class CommentChildren : IHaveCustomMapping
{
public string Id { get; set; }
/// <summary>
/// 回复时间
/// </summary>
public DateTime PublishTime { get; set; }
/// <summary>
/// 评论人
/// </summary>
[JsonConverter(typeof(CommenterConverter))]
public VmCommenter Commenter { get; set; }
/// <summary>
/// 回复内容
/// </summary>
public string CommentText { get; set; }
/// <summary>
/// 回复ID
/// </summary>
public List<string> Replies { get; set; }
/// <summary>
/// 是否删除
/// </summary>
public bool? IsDelete { get; set; }
private IMapper _mapper = new Mapper(new MapperConfiguration(x =>
{
x.CreateMap<MembleCommenter, VmMemberCommenter>();
x.CreateMap<GuestCommenter, VmGuestCommenter>();
}));
public void CreateMappings(MapperConfigurationExpression cfg)
{
cfg.CreateMap<Comment, CommentChildren>().ConvertUsing((entity, _) =>
{
if (entity.IsDelete == true)
{
entity.Commenter = new GuestCommenter
{
Email = "",
NickName = "该用户发言已被删除",
Site = ""
};
entity.CommentText = "该用户发言因某些原因已被删除";
}
var viewModel = new CommentChildren
{
Id = entity.Id.ToString(),
PublishTime = entity.PublishTime.ToLocalTime(),
CommentText = entity.CommentText,
Replies = entity.Replies.Select(x => x.ToString()).ToList(),
IsDelete = entity.IsDelete,
Commenter = entity.Commenter switch
{
MembleCommenter membleCommenter => _mapper.Map<VmMemberCommenter>(membleCommenter),
GuestCommenter guestCommenter => _mapper.Map<VmGuestCommenter>(guestCommenter),
_ => null
}
};
return viewModel;
});
}
}
public abstract class VmCommenter
{
/// <summary>
/// 昵称
/// </summary>
public string NickName { get; set; }
}
/// <summary>
/// 登录会员评论
/// </summary>
public class VmMemberCommenter : VmCommenter, IMapFrom<MembleCommenter>
{
/// <summary>
/// 头像
/// </summary>
public string Avatar { get; set; }
/// <summary>
/// 身份标识
/// </summary>
public string Identity { get; set; }
}
/// <summary>
/// 匿名评论
/// </summary>
public class VmGuestCommenter : VmCommenter, IMapFrom<GuestCommenter>
{
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; } = "";
/// <summary>
/// 网站
/// </summary>
public string? Site { get; set; }
public string? EmailMd5 { get; private set; }
public void GenerateEmailMd5()
{
EmailMd5 = Email.GenerateHashMd5();
Email = "";
}
}
public class CommenterConverter : JsonConverter<VmCommenter>
{
public override VmCommenter? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null) return null;
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException("JsonTokenType.StartObject not found.");
if (!reader.Read() || reader.TokenType != JsonTokenType.PropertyName
|| reader.GetString() != "$type")
throw new JsonException("Property $type not found.");
if (!reader.Read() || reader.TokenType != JsonTokenType.String)
throw new JsonException("Value at $type is invalid.");
var typeStr = reader.GetString();
var type = typeStr switch
{
"GuestCommenter" => typeof(VmGuestCommenter),
"MemberCommenter" => typeof(VmMemberCommenter),
_ => typeof(Commenter)
};
using var output = new MemoryStream();
ReadObject(ref reader, output, options);
var result = JsonSerializer.Deserialize(output.ToArray(), type, options);
return result as VmCommenter;
}
private void ReadObject(ref Utf8JsonReader reader, Stream output, JsonSerializerOptions options)
{
using var writer = new Utf8JsonWriter(output, new JsonWriterOptions
{
Encoder = options.Encoder,
Indented = options.WriteIndented
});
writer.WriteStartObject();
var objectIntend = 0;
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.None:
case JsonTokenType.Null:
writer.WriteNullValue();
break;
case JsonTokenType.StartObject:
writer.WriteStartObject();
objectIntend++;
break;
case JsonTokenType.EndObject:
writer.WriteEndObject();
if (objectIntend == 0)
{
writer.Flush();
return;
}
objectIntend--;
break;
case JsonTokenType.StartArray:
writer.WriteStartArray();
break;
case JsonTokenType.EndArray:
writer.WriteEndArray();
break;
case JsonTokenType.PropertyName:
writer.WritePropertyName(reader.GetString() ?? "");
break;
case JsonTokenType.Comment:
writer.WriteCommentValue(reader.GetComment());
break;
case JsonTokenType.String:
writer.WriteStringValue(reader.GetString());
break;
case JsonTokenType.Number:
writer.WriteNumberValue(reader.GetInt32());
break;
case JsonTokenType.True:
case JsonTokenType.False:
writer.WriteBooleanValue(reader.GetBoolean());
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public override void Write(Utf8JsonWriter writer, VmCommenter value, JsonSerializerOptions options)
{
writer.WriteStartObject();
var valueType = value.GetType();
//var valueAssemblyName = valueType.Assembly.GetName();
writer.WriteString("$type", $"{valueType.Name.Replace("Vm", "")}");
var json = JsonSerializer.Serialize(value, value.GetType(), options);
using (var document = JsonDocument.Parse(json, new JsonDocumentOptions
{
AllowTrailingCommas = options.AllowTrailingCommas,
MaxDepth = options.MaxDepth
}))
{
foreach (var jsonProperty in document.RootElement.EnumerateObject())
jsonProperty.WriteTo(writer);
}
writer.WriteEndObject();
}
}