Browse Source

增加 AreDailyMissionObjectivesSatisfied:按任务配置里每一条 MissionProgress,检查对应 CharacterMissionProgress 是否存在且 CurrentCount >= TargetCount(与战斗结算、MissionProgressService 的规则一致)。

CheckAndCompleteExpiredMissions:
超时且目标全部达成 → 仍为 Completed(可在时限结束前打完)。
超时但未达成 → 删除该每日实例下的 CharacterMissionProgress,任务回到 Pending,清空 StartTime / EndTime,并发一条系统聊天说明可重新接取。
master
秦汉 2 weeks ago
parent
commit
71096c1ee9
  1. 63
      Build_God_Api/Build_God_Api/Services/DailyMissionService.cs
  2. 21
      Build_God_Game/src/views/DailyMissionView.vue

63
Build_God_Api/Build_God_Api/Services/DailyMissionService.cs

@ -22,7 +22,8 @@ namespace Build_God_Api.Services
Task<bool> ClaimReward(int characterId, int dailyMissionId);
/// <summary>
/// 检查并完成所有到期任务
/// 检查进行中任务的时限:仅在客观目标(击杀/收集等)已全部达成时标记为完成;
/// 超时且未达成的重置为待接取并清除进度记录。
/// </summary>
Task CheckAndCompleteExpiredMissions();
@ -316,6 +317,25 @@ namespace Build_God_Api.Services
return true;
}
private async Task<bool> AreDailyMissionObjectivesSatisfied(int dailyMissionId, Mission mission)
{
if (mission.Progresses == null || mission.Progresses.Count == 0)
return false;
var characterProgressList = await _db.Queryable<CharacterMissionProgress>()
.Where(x => x.DailyMissionId == dailyMissionId)
.ToListAsync();
foreach (var p in mission.Progresses)
{
var cp = characterProgressList.FirstOrDefault(x => x.MissionProgressId == p.Id);
if (cp == null || cp.CurrentCount < p.TargetCount)
return false;
}
return true;
}
public async Task CheckAndCompleteExpiredMissions()
{
var now = GetBeijingTime();
@ -324,12 +344,45 @@ namespace Build_God_Api.Services
.Where(x => x.Status == DailyMissionStatus.InProgress && x.EndTime <= now)
.ToListAsync();
foreach (var mission in expiredMissions)
foreach (var dm in expiredMissions)
{
mission.Status = DailyMissionStatus.Completed;
await _db.Updateable(mission).ExecuteCommandAsync();
var mission = await _db.Queryable<Mission>()
.Includes(x => x.Progresses)
.FirstAsync(x => x.Id == dm.MissionId);
if (mission == null)
continue;
if (await AreDailyMissionObjectivesSatisfied(dm.Id, mission))
{
dm.Status = DailyMissionStatus.Completed;
await _db.Updateable(dm).ExecuteCommandAsync();
_logger.LogInformation("任务 {MissionId} 已自动完成,等待角色 {CharacterId} 领取", mission.MissionId, mission.CharacterId);
_logger.LogInformation(
"每日任务实例 {DailyMissionId}(配置 {MissionId})已在时限内达成目标,角色 {CharacterId} 待领取",
dm.Id, dm.MissionId, dm.CharacterId);
}
else
{
await _db.Deleteable<CharacterMissionProgress>()
.Where(x => x.DailyMissionId == dm.Id)
.ExecuteCommandAsync();
dm.Status = DailyMissionStatus.Pending;
dm.StartTime = null;
dm.EndTime = null;
await _db.Updateable(dm).ExecuteCommandAsync();
var character = await _db.Queryable<Character>()
.FirstAsync(x => x.Id == dm.CharacterId);
var msg = $"【{mission.Title}】未在限时内完成目标,任务已重置为待接取。";
await _chatService.AddMessageAsync(dm.CharacterId, character?.Name ?? "玩家", msg, ChatMessageType.System);
_logger.LogInformation(
"角色 {CharacterId} 的每日任务实例 {DailyMissionId} 超时未完成,已重置为待接取",
dm.CharacterId, dm.Id);
}
}
}

21
Build_God_Game/src/views/DailyMissionView.vue

@ -214,10 +214,10 @@ const MissionCardContent = defineComponent({
h('span', { class: ['card-status', getStatusClass(props.mission.status)] }, getStatusText(props.mission.status)),
]),
h('div', { class: 'card-desc' }, props.mission.missionDescription),
//h('div', { class: 'card-meta-row' }, [
//h('span', { class: ['difficulty-badge', getDifficultyClass(props.mission.difficulty)] }, getDifficultyLabel(props.mission.difficulty)),
//h('span', { class: 'time-badge' }, ` ${props.mission.spendTimeMinutes} `),
//]),
h('div', { class: 'card-meta-row' }, [
//h('span', { class: ['difficulty-badge', getDifficultyClass(props.mission.difficulty)] }, getDifficultyLabel(props.mission.difficulty)),
h('span', { class: 'time-badge' }, `限时 ${props.mission.spendTimeMinutes} 分钟`),
]),
props.mission.progresses && props.mission.progresses.length > 0
? h('div', { class: 'objective-panel' }, [
h('span', { class: 'objective-label' }, '任务目标'),
@ -599,14 +599,11 @@ const MissionCardContent = defineComponent({
font-weight: 700;
}
.time-badge {
padding: 4px 10px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.08);
color: #9ca3af;
font-size: 0.72rem;
font-weight: 600;
:deep(.time-badge) {
color: #aaaaaa;
font-size: 0.84rem;
line-height: 1.55;
margin: 0;
}
.difficulty-normal {

Loading…
Cancel
Save