Merge branch 'master' of http://8.137.159.94:3000/glz/QYZH.InteractiveMagazine
This commit is contained in:
@ -59,6 +59,37 @@ public class BindJournalOutput
|
|||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户绑定期刊消息
|
||||||
|
/// </summary>
|
||||||
|
public class BindJournalMessage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户Id
|
||||||
|
/// </summary>
|
||||||
|
public long UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 期刊Id
|
||||||
|
/// </summary>
|
||||||
|
public long JournalId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 期刊开始时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? StartTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 期刊结束时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? EndTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户作答信息上传地址
|
||||||
|
/// </summary>
|
||||||
|
public string UploadDomain { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户期刊关联查询输入DTO
|
/// 用户期刊关联查询输入DTO
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -55,6 +55,11 @@ public class UsersOutput
|
|||||||
/// 当前成长值
|
/// 当前成长值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int GrowthPoints { get; set; }
|
public int GrowthPoints { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户作答信息上传地址
|
||||||
|
/// </summary>
|
||||||
|
public string UploadDomain { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -146,6 +146,11 @@ public class WxUserOutput
|
|||||||
/// 创建时间
|
/// 创建时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户作答信息上传地址
|
||||||
|
/// </summary>
|
||||||
|
public string UploadDomain { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
25
QYZH.InteractiveMagazine.Models/Entity/UploadDomain.cs
Normal file
25
QYZH.InteractiveMagazine.Models/Entity/UploadDomain.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace QYZH.InteractiveMagazine.Models.Entity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 上传地址管理表
|
||||||
|
/// </summary>
|
||||||
|
[SugarTable("UploadDomain")]
|
||||||
|
public partial class UploadDomain : SqlSugarBaseEntity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Desc:上传地址
|
||||||
|
/// Default:
|
||||||
|
/// Nullable:False
|
||||||
|
/// </summary>
|
||||||
|
public string Domain { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Desc:已分配人数
|
||||||
|
/// Default:0
|
||||||
|
/// Nullable:False
|
||||||
|
/// </summary>
|
||||||
|
public int AssignedCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -57,5 +57,12 @@ namespace QYZH.InteractiveMagazine.Models.Entity
|
|||||||
/// Nullable:False
|
/// Nullable:False
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsLastOnline { get; set; }
|
public bool IsLastOnline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Desc:用户作答信息上传地址
|
||||||
|
/// Default:
|
||||||
|
/// Nullable:False
|
||||||
|
/// </summary>
|
||||||
|
public string UploadDomain { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto;
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
@ -17,9 +18,14 @@ public class UserJournalService(
|
|||||||
BaseRepository<Users> usersRepository,
|
BaseRepository<Users> usersRepository,
|
||||||
BaseRepository<Journal> journalRepository,
|
BaseRepository<Journal> journalRepository,
|
||||||
ILogger<UserJournalService> logger,
|
ILogger<UserJournalService> logger,
|
||||||
|
IRabbitMQService rabbitMqService,
|
||||||
IPetService petService)
|
IPetService petService)
|
||||||
: BaseRepository<UserJournal>, IUserJournalService
|
: BaseRepository<UserJournal>, IUserJournalService
|
||||||
{
|
{
|
||||||
|
private const string JournalExchange = "ex.journal";
|
||||||
|
private const string BindJournalQueue = "mq.journal.bindUser";
|
||||||
|
private const string BindJournalRoutingKey = "rk.journal.bindUser";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户绑定期刊(扫码绑定)
|
/// 用户绑定期刊(扫码绑定)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -93,6 +99,7 @@ public class UserJournalService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("用户绑定期刊成功,UserId: {UserId}, JournalId: {JournalId}, Id: {Id}", userId, input.JournalId, userJournal.Id);
|
logger.LogInformation("用户绑定期刊成功,UserId: {UserId}, JournalId: {JournalId}, Id: {Id}", userId, input.JournalId, userJournal.Id);
|
||||||
|
await SendBindJournalMessageAsync(user, journal);
|
||||||
|
|
||||||
// 首次绑定期刊时激活宠物
|
// 首次绑定期刊时激活宠物
|
||||||
if (isFirstBind)
|
if (isFirstBind)
|
||||||
@ -119,6 +126,36 @@ public class UserJournalService(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SendBindJournalMessageAsync(Users user, Journal journal)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var messageSent = await rabbitMqService.SendAsync(new RabbitMQSendParam
|
||||||
|
{
|
||||||
|
Exchange = JournalExchange,
|
||||||
|
Queue = BindJournalQueue,
|
||||||
|
RoutingKey = BindJournalRoutingKey,
|
||||||
|
Data = new BindJournalMessage
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
JournalId = journal.Id,
|
||||||
|
StartTime = journal.StartTime,
|
||||||
|
EndTime = journal.EndTime,
|
||||||
|
UploadDomain = user.UploadDomain
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!messageSent)
|
||||||
|
{
|
||||||
|
logger.LogError("发送绑定期刊消息失败,UserId: {UserId}, JournalId: {JournalId}", user.Id, journal.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "发送绑定期刊消息异常,UserId: {UserId}, JournalId: {JournalId}", user.Id, journal.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取用户的期刊绑定列表
|
/// 获取用户的期刊绑定列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -19,6 +19,7 @@ namespace QYZH.InteractiveMagazine.Service;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class WeChatAuthService(
|
public class WeChatAuthService(
|
||||||
BaseRepository<WxUser> wxUserRepository,
|
BaseRepository<WxUser> wxUserRepository,
|
||||||
|
BaseRepository<UploadDomain> uploadDomainRepository,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
ILogger<WeChatAuthService> logger,
|
ILogger<WeChatAuthService> logger,
|
||||||
IPetService petService)
|
IPetService petService)
|
||||||
@ -260,7 +261,27 @@ public class WeChatAuthService(
|
|||||||
UpdatedAt = DateTime.Now
|
UpdatedAt = DateTime.Now
|
||||||
};
|
};
|
||||||
|
|
||||||
await wxUserRepository.Context.Insertable(newUser).ExecuteReturnIdentityAsync();
|
await UseTranAsync(async () =>
|
||||||
|
{
|
||||||
|
var uploadDomain = await uploadDomainRepository.Queryable()
|
||||||
|
.Where(d => d.Status == 1 && !d.IsDeleted)
|
||||||
|
.OrderBy(d => d.AssignedCount, SqlSugar.OrderByType.Asc)
|
||||||
|
.OrderBy(d => d.Id, SqlSugar.OrderByType.Asc)
|
||||||
|
.FirstAsync();
|
||||||
|
|
||||||
|
BusinessException.ThrowIf(uploadDomain == null, "暂无可用上传地址,请联系管理员", ResultCode.UNPROCESSABLE_ENTITY);
|
||||||
|
|
||||||
|
newUser.UploadDomain = uploadDomain!.Domain;
|
||||||
|
|
||||||
|
await wxUserRepository.Context.Insertable(newUser).ExecuteCommandAsync();
|
||||||
|
|
||||||
|
await uploadDomainRepository.Updateable()
|
||||||
|
.SetColumns(d => d.AssignedCount == d.AssignedCount + 1)
|
||||||
|
.SetColumns(d => d.UpdatedBy == wxUserId.ToString())
|
||||||
|
.SetColumns(d => d.UpdatedAt == DateTime.Now)
|
||||||
|
.Where(d => d.Id == uploadDomain.Id)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
});
|
||||||
|
|
||||||
logger.LogInformation("新用户创建成功,UserId: {UserId}, WxUserId: {WxUserId}, Name: {Name}",
|
logger.LogInformation("新用户创建成功,UserId: {UserId}, WxUserId: {WxUserId}, Name: {Name}",
|
||||||
newUser.Id, wxUserId, input.Name);
|
newUser.Id, wxUserId, input.Name);
|
||||||
@ -431,7 +452,8 @@ public class WeChatAuthService(
|
|||||||
Type = user.Type.ToString(),
|
Type = user.Type.ToString(),
|
||||||
Status = user.Status.ToString(),
|
Status = user.Status.ToString(),
|
||||||
IsLastOnline = user.IsLastOnline,
|
IsLastOnline = user.IsLastOnline,
|
||||||
CreatedAt = user.CreatedAt
|
CreatedAt = user.CreatedAt,
|
||||||
|
UploadDomain = user.UploadDomain
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,14 @@ public class JournalController : WeChatBaseController
|
|||||||
private readonly IUserJournalService _userJournalService;
|
private readonly IUserJournalService _userJournalService;
|
||||||
private readonly ILogger<JournalController> _logger;
|
private readonly ILogger<JournalController> _logger;
|
||||||
|
|
||||||
public JournalController(IUserJournalService userJournalService, ILogger<JournalController> logger)
|
/// <summary>
|
||||||
|
/// 初始化小程序期刊控制器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userJournalService">用户期刊关联服务</param>
|
||||||
|
/// <param name="logger">日志服务</param>
|
||||||
|
public JournalController(
|
||||||
|
IUserJournalService userJournalService,
|
||||||
|
ILogger<JournalController> logger)
|
||||||
{
|
{
|
||||||
_userJournalService = userJournalService;
|
_userJournalService = userJournalService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|||||||
@ -22,6 +22,8 @@ public class JournalTaskReceiveConsumer(
|
|||||||
private const int DefaultAiScoreMaxRetryCount = 3;
|
private const int DefaultAiScoreMaxRetryCount = 3;
|
||||||
private const int DefaultAiScoreRetryDelayMilliseconds = 1000;
|
private const int DefaultAiScoreRetryDelayMilliseconds = 1000;
|
||||||
private const long DefaultMaxImageBytes = 10 * 1024 * 1024;
|
private const long DefaultMaxImageBytes = 10 * 1024 * 1024;
|
||||||
|
private const float DefaultCompletionThreshold = 80;
|
||||||
|
private const float DefaultCommunityScoreThreshold = 90;
|
||||||
|
|
||||||
public string Exchange => "ex.journal";
|
public string Exchange => "ex.journal";
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ public class JournalTaskReceiveConsumer(
|
|||||||
.Where(p => p.Id == data.PageId && !p.IsDeleted)
|
.Where(p => p.Id == data.PageId && !p.IsDeleted)
|
||||||
.FirstAsync(cancellationToken);
|
.FirstAsync(cancellationToken);
|
||||||
|
|
||||||
var answerEntities = new List<JournalPageTaskUserAnswer>();
|
var answerContexts = new List<JournalAnswerContext>();
|
||||||
foreach (var question in data.Questions)
|
foreach (var question in data.Questions)
|
||||||
{
|
{
|
||||||
if (!taskMap.TryGetValue(question.Id, out var task))
|
if (!taskMap.TryGetValue(question.Id, out var task))
|
||||||
@ -80,10 +82,14 @@ public class JournalTaskReceiveConsumer(
|
|||||||
|
|
||||||
referenceAnswerMap.TryGetValue(task.Id, out var taskReferenceAnswers);
|
referenceAnswerMap.TryGetValue(task.Id, out var taskReferenceAnswers);
|
||||||
var scoreResult = await ScoreQuestionAsync(task, question, taskReferenceAnswers ?? [], cancellationToken);
|
var scoreResult = await ScoreQuestionAsync(task, question, taskReferenceAnswers ?? [], cancellationToken);
|
||||||
answerEntities.Add(BuildAnswerEntity(data, question, task, page, scoreResult));
|
answerContexts.Add(new JournalAnswerContext(
|
||||||
|
BuildAnswerEntity(data, question, task, page, scoreResult, GetCompletionThreshold()),
|
||||||
|
question,
|
||||||
|
task,
|
||||||
|
scoreResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (answerEntities.Count == 0)
|
if (answerContexts.Count == 0)
|
||||||
{
|
{
|
||||||
logger.LogWarning("期刊任务消息没有可入库的答题记录,UserId: {UserId}, JournalId: {JournalId}, PageId: {PageId}", data.UserId, data.JournalId, data.PageId);
|
logger.LogWarning("期刊任务消息没有可入库的答题记录,UserId: {UserId}, JournalId: {JournalId}, PageId: {PageId}", data.UserId, data.JournalId, data.PageId);
|
||||||
return;
|
return;
|
||||||
@ -92,8 +98,9 @@ public class JournalTaskReceiveConsumer(
|
|||||||
client.Ado.BeginTran();
|
client.Ado.BeginTran();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var answer in answerEntities)
|
foreach (var context in answerContexts)
|
||||||
{
|
{
|
||||||
|
var answer = context.Answer;
|
||||||
var existing = await client.Queryable<JournalPageTaskUserAnswer>()
|
var existing = await client.Queryable<JournalPageTaskUserAnswer>()
|
||||||
.Where(a => a.UserId == answer.UserId && a.JournalPageTaskId == answer.JournalPageTaskId && !a.IsDeleted)
|
.Where(a => a.UserId == answer.UserId && a.JournalPageTaskId == answer.JournalPageTaskId && !a.IsDeleted)
|
||||||
.FirstAsync(cancellationToken);
|
.FirstAsync(cancellationToken);
|
||||||
@ -101,21 +108,24 @@ public class JournalTaskReceiveConsumer(
|
|||||||
if (existing == null)
|
if (existing == null)
|
||||||
{
|
{
|
||||||
await client.Insertable(answer).ExecuteCommandAsync(cancellationToken);
|
await client.Insertable(answer).ExecuteCommandAsync(cancellationToken);
|
||||||
continue;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await client.Insertable(BuildAnswerSnapshot(existing)).ExecuteCommandAsync(cancellationToken);
|
||||||
|
|
||||||
|
answer.Id = existing.Id;
|
||||||
|
answer.CreatedBy = existing.CreatedBy;
|
||||||
|
answer.CreatedAt = existing.CreatedAt;
|
||||||
|
answer.UpdatedBy = answer.UserId.ToString();
|
||||||
|
answer.UpdatedAt = DateTime.Now;
|
||||||
|
|
||||||
|
await client.Updateable(answer)
|
||||||
|
.IgnoreColumns(a => new { a.CreatedBy, a.CreatedAt })
|
||||||
|
.Where(a => a.Id == existing.Id)
|
||||||
|
.ExecuteCommandAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.Insertable(BuildAnswerSnapshot(existing)).ExecuteCommandAsync(cancellationToken);
|
await InsertCommunityMessageIfNeededAsync(client, context, cancellationToken);
|
||||||
|
|
||||||
answer.Id = existing.Id;
|
|
||||||
answer.CreatedBy = existing.CreatedBy;
|
|
||||||
answer.CreatedAt = existing.CreatedAt;
|
|
||||||
answer.UpdatedBy = answer.UserId.ToString();
|
|
||||||
answer.UpdatedAt = DateTime.Now;
|
|
||||||
|
|
||||||
await client.Updateable(answer)
|
|
||||||
.IgnoreColumns(a => new { a.CreatedBy, a.CreatedAt })
|
|
||||||
.Where(a => a.Id == existing.Id)
|
|
||||||
.ExecuteCommandAsync(cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Ado.CommitTran();
|
client.Ado.CommitTran();
|
||||||
@ -127,7 +137,7 @@ public class JournalTaskReceiveConsumer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("期刊任务答题记录保存完成,UserId: {UserId}, JournalId: {JournalId}, PageId: {PageId}, Count: {Count}",
|
logger.LogInformation("期刊任务答题记录保存完成,UserId: {UserId}, JournalId: {JournalId}, PageId: {PageId}, Count: {Count}",
|
||||||
data.UserId, data.JournalId, data.PageId, answerEntities.Count);
|
data.UserId, data.JournalId, data.PageId, answerContexts.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task OnErrorAsync(byte[] body, Exception exception)
|
public Task OnErrorAsync(byte[] body, Exception exception)
|
||||||
@ -293,6 +303,7 @@ public class JournalTaskReceiveConsumer(
|
|||||||
prompt.AppendLine(" \"Judgment\": 0,");
|
prompt.AppendLine(" \"Judgment\": 0,");
|
||||||
prompt.AppendLine(" \"Expression\": 0,");
|
prompt.AppendLine(" \"Expression\": 0,");
|
||||||
prompt.AppendLine(" \"Persuasiveness\": 0,");
|
prompt.AppendLine(" \"Persuasiveness\": 0,");
|
||||||
|
prompt.AppendLine(" \"Completion\": 100,");
|
||||||
prompt.AppendLine(" \"Result\": \"50字内的中文评语\"");
|
prompt.AppendLine(" \"Result\": \"50字内的中文评语\"");
|
||||||
prompt.AppendLine("}");
|
prompt.AppendLine("}");
|
||||||
return prompt.ToString();
|
return prompt.ToString();
|
||||||
@ -566,11 +577,15 @@ public class JournalTaskReceiveConsumer(
|
|||||||
Question question,
|
Question question,
|
||||||
JournalPageTask task,
|
JournalPageTask task,
|
||||||
JournalPage? page,
|
JournalPage? page,
|
||||||
JournalAnswerScoreResult scoreResult)
|
JournalAnswerScoreResult scoreResult,
|
||||||
|
float completionThreshold)
|
||||||
{
|
{
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var growthPoint = Math.Max(0, scoreResult.GrowthPoint);
|
var growthPoint = Math.Max(0, scoreResult.GrowthPoint);
|
||||||
var points = Math.Max(0, scoreResult.Points);
|
var points = Math.Max(0, scoreResult.Points);
|
||||||
|
var answerStatus = scoreResult.Completion >= completionThreshold
|
||||||
|
? UserAnswerStatusEnum.Complete
|
||||||
|
: UserAnswerStatusEnum.Processing;
|
||||||
|
|
||||||
return new JournalPageTaskUserAnswer
|
return new JournalPageTaskUserAnswer
|
||||||
{
|
{
|
||||||
@ -605,8 +620,8 @@ public class JournalTaskReceiveConsumer(
|
|||||||
PageAnswerDotUrl = string.Empty,
|
PageAnswerDotUrl = string.Empty,
|
||||||
BreakCount = question.BreakCount,
|
BreakCount = question.BreakCount,
|
||||||
BreakTimes = JsonSerializer.Serialize(question.BreakTimes ?? []),
|
BreakTimes = JsonSerializer.Serialize(question.BreakTimes ?? []),
|
||||||
AssignmentStatus = UserAnswerStatusEnum.Complete.ToString(),
|
AssignmentStatus = answerStatus.ToString(),
|
||||||
Status = (int)UserAnswerStatusEnum.Complete,
|
Status = (int)answerStatus,
|
||||||
CreatedBy = data.UserId.ToString(),
|
CreatedBy = data.UserId.ToString(),
|
||||||
CreatedAt = data.CreatedTime == default ? now : data.CreatedTime,
|
CreatedAt = data.CreatedTime == default ? now : data.CreatedTime,
|
||||||
UpdatedBy = data.UserId.ToString(),
|
UpdatedBy = data.UserId.ToString(),
|
||||||
@ -660,6 +675,76 @@ public class JournalTaskReceiveConsumer(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task InsertCommunityMessageIfNeededAsync(
|
||||||
|
ISqlSugarClient client,
|
||||||
|
JournalAnswerContext context,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var scoreThreshold = configuration.GetValue<float>("AiChat:CommunityScoreThreshold");
|
||||||
|
if (scoreThreshold <= 0)
|
||||||
|
{
|
||||||
|
scoreThreshold = DefaultCommunityScoreThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Answer.Status != (int)UserAnswerStatusEnum.Complete || context.ScoreResult.Score < scoreThreshold)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var exists = await client.Queryable<CommunityMessage>()
|
||||||
|
.Where(m => m.JournalTaskAnswerId == context.Answer.Id && !m.IsDeleted)
|
||||||
|
.AnyAsync(cancellationToken);
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userJournal = await client.Queryable<UserJournal>()
|
||||||
|
.Where(uj => uj.UserId == context.Answer.UserId && uj.JournalId == context.Answer.JournalId && !uj.IsDeleted)
|
||||||
|
.FirstAsync(cancellationToken);
|
||||||
|
if (userJournal == null)
|
||||||
|
{
|
||||||
|
logger.LogWarning("高分答案未找到用户期刊关系,跳过社区消息写入,UserId: {UserId}, JournalId: {JournalId}, AnswerId: {AnswerId}",
|
||||||
|
context.Answer.UserId, context.Answer.JournalId, context.Answer.Id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var communityMessage = new CommunityMessage
|
||||||
|
{
|
||||||
|
JournalId = context.Answer.JournalId,
|
||||||
|
UserId = context.Answer.UserId,
|
||||||
|
UserJournalId = userJournal.Id,
|
||||||
|
JournalTaskId = context.Answer.JournalPageTaskId,
|
||||||
|
JournalTaskAnswerId = context.Answer.Id,
|
||||||
|
Content = context.ScoreResult.Result,
|
||||||
|
ImageUrl = context.Question.AnswerUrl.FirstOrDefault() ?? string.Empty,
|
||||||
|
SortOrder = 0,
|
||||||
|
IsActive = true,
|
||||||
|
Type = MessageTypeEnum.Message,
|
||||||
|
LikeCount = 0,
|
||||||
|
IsFeatured = 0,
|
||||||
|
Status = 1,
|
||||||
|
CreatedBy = context.Answer.UserId.ToString(),
|
||||||
|
CreatedAt = now,
|
||||||
|
UpdatedBy = context.Answer.UserId.ToString(),
|
||||||
|
UpdatedAt = now
|
||||||
|
};
|
||||||
|
|
||||||
|
await client.Insertable(communityMessage).ExecuteCommandAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetCompletionThreshold()
|
||||||
|
{
|
||||||
|
var threshold = configuration.GetValue<float>("AiChat:CompletionThreshold");
|
||||||
|
if (threshold <= 0)
|
||||||
|
{
|
||||||
|
threshold = DefaultCompletionThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
private static string TrimResult(string? result)
|
private static string TrimResult(string? result)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(result))
|
if (string.IsNullOrWhiteSpace(result))
|
||||||
@ -809,10 +894,21 @@ public class JournalAnswerScoreResult
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float Persuasiveness { get; set; }
|
public float Persuasiveness { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 瀹屾垚搴?
|
||||||
|
/// </summary>
|
||||||
|
public float Completion { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 50字内评语
|
/// 50字内评语
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Result { get; set; } = string.Empty;
|
public string Result { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record JournalAnswerContext(
|
||||||
|
JournalPageTaskUserAnswer Answer,
|
||||||
|
Question Question,
|
||||||
|
JournalPageTask Task,
|
||||||
|
JournalAnswerScoreResult ScoreResult);
|
||||||
|
|
||||||
public record AnswerImageContent(string DataUrl);
|
public record AnswerImageContent(string DataUrl);
|
||||||
|
|||||||
@ -58,7 +58,9 @@
|
|||||||
"Temperature": 0.5,
|
"Temperature": 0.5,
|
||||||
"ScoreMaxRetryCount": 3,
|
"ScoreMaxRetryCount": 3,
|
||||||
"ScoreRetryDelayMilliseconds": 1000,
|
"ScoreRetryDelayMilliseconds": 1000,
|
||||||
"MaxImageBytes": 10485760
|
"MaxImageBytes": 10485760,
|
||||||
|
"CompletionThreshold": 80,
|
||||||
|
"CommunityScoreThreshold": 90
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"AliyunOSSConfigs": {
|
"AliyunOSSConfigs": {
|
||||||
|
|||||||
Reference in New Issue
Block a user