diff --git a/Build_God_Admin_Frontend/Frontend/.env.development b/Build_God_Admin_Frontend/Frontend/.env.development index b580ebe..40bd306 100644 --- a/Build_God_Admin_Frontend/Frontend/.env.development +++ b/Build_God_Admin_Frontend/Frontend/.env.development @@ -1,2 +1,2 @@ # 开发环境配置 -VITE_API_URL=https://localhost:59447/api/god/ +VITE_API_URL=http://localhost:5091/api/god/ diff --git a/Build_God_Admin_Frontend/Frontend/src/api/bag.ts b/Build_God_Admin_Frontend/Frontend/src/api/bag.ts index 165fc10..565ee49 100644 --- a/Build_God_Admin_Frontend/Frontend/src/api/bag.ts +++ b/Build_God_Admin_Frontend/Frontend/src/api/bag.ts @@ -73,7 +73,7 @@ export const GetBagItems = (characterBagId: number): Promise => { } export const AddItemToBag = (characterBagId: number, data: AddBagItemDto): Promise => { - return http.post(`bag/${characterBagId}/items`, data) + return http.post(`bag/${characterBagId}/items/with-mission`, data) } export const RemoveItemFromBag = (characterBagId: number, itemId: number): Promise => { diff --git a/Build_God_Api/Build_God_Api/Controllers/BagController.cs b/Build_God_Api/Build_God_Api/Controllers/BagController.cs index 5b6754e..e21f492 100644 --- a/Build_God_Api/Build_God_Api/Controllers/BagController.cs +++ b/Build_God_Api/Build_God_Api/Controllers/BagController.cs @@ -8,9 +8,13 @@ namespace Build_God_Api.Controllers { [ApiController] [Route("api/god/[controller]")] - public class BagController(IBagService service) : ControllerBase + public class BagController( + IBagService service, + IMissionProgressService missionProgressService + ) : ControllerBase { private readonly IBagService service = service; + private readonly IMissionProgressService missionProgressService = missionProgressService; // ============ Bag配置管理 ============ @@ -82,6 +86,13 @@ namespace Build_God_Api.Controllers return await service.AddItemToBag(characterBagId, dto.ItemType, dto.ItemId, dto.Quantity); } + [HttpPost("{characterBagId}/items/with-mission")] + [Authorize] + public async Task> AddItemToBagWithMission(int characterBagId, [FromBody] AddBagItemDto dto) + { + return await service.AddItemToBagWithMissionProgress(characterBagId, dto.ItemType, dto.ItemId, dto.Quantity, missionProgressService); + } + [HttpDelete("{characterBagId}/items/{itemId}")] [Authorize(Roles = "admin")] public async Task> RemoveItemFromBag(int characterBagId, int itemId) diff --git a/Build_God_Api/Build_God_Api/Controllers/MissionController.cs b/Build_God_Api/Build_God_Api/Controllers/MissionController.cs index f471fa9..1133ac1 100644 --- a/Build_God_Api/Build_God_Api/Controllers/MissionController.cs +++ b/Build_God_Api/Build_God_Api/Controllers/MissionController.cs @@ -11,11 +11,15 @@ namespace Build_God_Api.Controllers [Route("api/god/[controller]")] public class MissionController( IMissionService service, - IMissionProgressService progressService + IMissionProgressService progressService, + ICharacterService characterService, + ICurrentUserService currentUserService ) : ControllerBase { private readonly IMissionService service = service; private readonly IMissionProgressService progressService = progressService; + private readonly ICharacterService characterService = characterService; + private readonly ICurrentUserService currentUserService = currentUserService; // ============ Mission ============ @@ -93,6 +97,31 @@ namespace Build_God_Api.Controllers return await progressService.Delete(id); } + [HttpPost("progress/update")] + [Authorize] + public async Task> UpdateProgress([FromBody] UpdateProgressCmd cmd) + { + try + { + var character = await characterService.GetCharacterByAccountId(currentUserService.UserId); + if (character == null) + return BadRequest("角色不存在"); + + var (success, missionCompleted) = await progressService.UpdateProgressByTargetType( + character.Id, cmd.ProgressType, cmd.ItemId, cmd.ItemName, cmd.Count); + + return Ok(new UpdateProgressResultDto + { + Success = success, + MissionCompleted = missionCompleted + }); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + // ============ Enums ============ [HttpGet("types")] diff --git a/Build_God_Api/Build_God_Api/DB/Mission.cs b/Build_God_Api/Build_God_Api/DB/Mission.cs index d1abfa2..cd9e491 100644 --- a/Build_God_Api/Build_God_Api/DB/Mission.cs +++ b/Build_God_Api/Build_God_Api/DB/Mission.cs @@ -20,7 +20,7 @@ namespace Build_God_Api.DB /// 任务类型 /// [SugarColumn(IsNullable = false)] - public MissionType Type { get; set; } = MissionType.MainStory; + public MissionType Type { get; set; } = MissionType.Collection; /// /// 任务标题(展示用,与Name不同) @@ -91,11 +91,11 @@ namespace Build_God_Api.DB /// public enum MissionType { - [Description("悬赏任务")] - MainStory = 1, + [Description("收集任务")] + Collection = 1, - [Description("日常任务")] - DailyTask = 2 + [Description("狩猎任务")] + Hunting = 2 } /// diff --git a/Build_God_Api/Build_God_Api/Dto/MissionDtos.cs b/Build_God_Api/Build_God_Api/Dto/MissionDtos.cs index b0d7a6a..71fa447 100644 --- a/Build_God_Api/Build_God_Api/Dto/MissionDtos.cs +++ b/Build_God_Api/Build_God_Api/Dto/MissionDtos.cs @@ -8,4 +8,18 @@ namespace Build_God_Api.Dto public int PageSize { get; set; } = 0; public int? MissionType { get; set; } } + + public class UpdateProgressCmd + { + public ProgressTargetType ProgressType { get; set; } + public int? ItemId { get; set; } + public string? ItemName { get; set; } + public int Count { get; set; } = 1; + } + + public class UpdateProgressResultDto + { + public bool Success { get; set; } + public bool MissionCompleted { get; set; } + } } diff --git a/Build_God_Api/Build_God_Api/Services/BagService.cs b/Build_God_Api/Build_God_Api/Services/BagService.cs index c7f83cb..da42629 100644 --- a/Build_God_Api/Build_God_Api/Services/BagService.cs +++ b/Build_God_Api/Build_God_Api/Services/BagService.cs @@ -1,4 +1,5 @@ using Build_God_Api.DB; +using Build_God_Api.Dto; using SqlSugar; namespace Build_God_Api.Services @@ -19,6 +20,7 @@ namespace Build_God_Api.Services // 背包物品管理 Task> GetBagItems(int characterBagId); Task AddItemToBag(int characterBagId, int itemType, int itemId, int quantity); + Task AddItemToBagWithMissionProgress(int characterBagId, int itemType, int itemId, int quantity, IMissionProgressService? missionProgressService = null); Task RemoveItemFromBag(int characterBagId, int bagItemId); // 物品数量管理 @@ -266,6 +268,39 @@ namespace Build_God_Api.Services return true; } + public async Task AddItemToBagWithMissionProgress(int characterBagId, int itemType, int itemId, int quantity, IMissionProgressService? missionProgressService = null) + { + var result = await AddItemToBag(characterBagId, itemType, itemId, quantity); + + if (result && missionProgressService != null) + { + var characterBag = await db.Queryable() + .FirstAsync(x => x.Id == characterBagId); + + if (characterBag != null) + { + var pill = await db.Queryable().FirstAsync(x => x.Id == itemId); + var itemName = pill?.Name ?? string.Empty; + + try + { + await missionProgressService.UpdateProgressByTargetType( + characterBag.CharacterId, + ProgressTargetType.CollectItem, + itemId, + itemName, + quantity); + } + catch + { + // 忽略任务进度更新错误,不影响物品添加 + } + } + } + + return result; + } + public async Task RemoveItemFromBag(int characterBagId, int bagItemId) { var item = await db.Queryable() diff --git a/Build_God_Api/Build_God_Api/Services/DailyMissionService.cs b/Build_God_Api/Build_God_Api/Services/DailyMissionService.cs index c2a3785..8cd0775 100644 --- a/Build_God_Api/Build_God_Api/Services/DailyMissionService.cs +++ b/Build_God_Api/Build_God_Api/Services/DailyMissionService.cs @@ -50,6 +50,9 @@ namespace Build_God_Api.Services public int TodayClaimedCount { get; set; } public int TodayTotalCount { get; set; } public List Rewards { get; set; } = new(); + public MissionType MissionType { get; set; } + public MissionDifficulty Difficulty { get; set; } + public List Progresses { get; set; } = new(); } public class MissionRewardDto @@ -61,6 +64,16 @@ namespace Build_God_Api.Services public int Count { get; set; } } + public class MissionProgressDto + { + public int MissionProgressId { get; set; } + public ProgressTargetType TargetType { get; set; } + public int? TargetItemId { get; set; } + public string? TargetItemName { get; set; } + public int TargetCount { get; set; } + public int CurrentCount { get; set; } + } + public class DailyMissionService( ISqlSugarClient db, IBagService bagService, @@ -125,6 +138,7 @@ namespace Build_God_Api.Services { var mission = await _db.Queryable() .Includes(x => x.Rewards) + .Includes(x => x.Progresses) .FirstAsync(x => x.Id == dm.MissionId); if (mission == null) continue; @@ -145,7 +159,9 @@ namespace Build_God_Api.Services AssignedDate = dm.AssignedDate, ExpReward = CalculateExpReward(mission.Difficulty, character.LevelId), TodayClaimedCount = todayClaimedCount, - TodayTotalCount = todayTotalCount + TodayTotalCount = todayTotalCount, + MissionType = mission.Type, + Difficulty = mission.Difficulty }; if (mission.Rewards != null) @@ -163,6 +179,25 @@ namespace Build_God_Api.Services } } + if (mission.Progresses != null) + { + foreach (var progress in mission.Progresses) + { + var characterProgress = await _db.Queryable() + .FirstAsync(x => x.CharacterId == characterId && x.MissionId == dm.MissionId && x.MissionProgressId == progress.Id); + + dto.Progresses.Add(new MissionProgressDto + { + MissionProgressId = progress.Id, + TargetType = progress.TargetType, + TargetItemId = progress.TargetItemId, + TargetItemName = progress.TargetItemName, + TargetCount = progress.TargetCount, + CurrentCount = characterProgress?.CurrentCount ?? 0 + }); + } + } + result.Add(dto); } @@ -312,7 +347,7 @@ namespace Build_God_Api.Services } var availableMissions = await _db.Queryable() - .Where(x => x.Type == MissionType.DailyTask) + .Where(x => x.Type == MissionType.Collection || x.Type == MissionType.Hunting) .Where(x => x.IsAvailable == true) .Where(x => x.RequiredLevelId <= character.LevelId) .ToListAsync(); diff --git a/Build_God_Api/Build_God_Api/Services/MissionProgressService.cs b/Build_God_Api/Build_God_Api/Services/MissionProgressService.cs index 469f001..c53d1ce 100644 --- a/Build_God_Api/Build_God_Api/Services/MissionProgressService.cs +++ b/Build_God_Api/Build_God_Api/Services/MissionProgressService.cs @@ -1,4 +1,5 @@ using Build_God_Api.DB; +using Build_God_Api.Dto; using SqlSugar; namespace Build_God_Api.Services @@ -16,6 +17,9 @@ namespace Build_God_Api.Services Task> GetCharacterProgress(int characterId, int missionId); Task UpdateCharacterProgress(int characterId, int missionProgressId, int count); Task InitCharacterProgress(int characterId, int missionId); + + // 更新角色任务进度(根据目标类型自动匹配) + Task<(bool success, bool missionCompleted)> UpdateProgressByTargetType(int characterId, ProgressTargetType targetType, int? itemId, string? itemName, int count); } public class MissionProgressService(ISqlSugarClient db) : IMissionProgressService @@ -125,5 +129,84 @@ namespace Build_God_Api.Services return true; } + + public async Task<(bool success, bool missionCompleted)> UpdateProgressByTargetType(int characterId, ProgressTargetType targetType, int? itemId, string? itemName, int count) + { + // 查找该角色所有进行中的每日任务 + var dailyMissions = await db.Queryable() + .Where(x => x.CharacterId == characterId && x.Status == DailyMissionStatus.InProgress) + .ToListAsync(); + + if (!dailyMissions.Any()) + return (false, false); + + bool anyCompleted = false; + + foreach (var dailyMission in dailyMissions) + { + // 获取任务配置 + var mission = await db.Queryable() + .Includes(x => x.Progresses) + .FirstAsync(x => x.Id == dailyMission.MissionId); + + if (mission?.Progresses == null || !mission.Progresses.Any()) + continue; + + // 查找匹配的目标进度 + var matchingProgress = mission.Progresses.FirstOrDefault(p => + p.TargetType == targetType && + (targetType != ProgressTargetType.CollectItem || p.TargetItemId == itemId)); + + if (matchingProgress == null) + continue; + + // 获取角色进度 + var characterProgress = await db.Queryable() + .FirstAsync(x => + x.CharacterId == characterId && + x.MissionId == dailyMission.MissionId && + x.MissionProgressId == matchingProgress.Id); + + if (characterProgress == null) + { + characterProgress = new CharacterMissionProgress + { + CharacterId = characterId, + MissionId = dailyMission.MissionId, + MissionProgressId = matchingProgress.Id, + CurrentCount = 0, + IsCompleted = false, + UpdatedOn = DateTime.UtcNow + }; + await db.Insertable(characterProgress).ExecuteCommandAsync(); + } + + if (characterProgress.IsCompleted) + continue; + + // 更新进度 + characterProgress.CurrentCount = Math.Min(characterProgress.CurrentCount + count, matchingProgress.TargetCount); + characterProgress.IsCompleted = characterProgress.CurrentCount >= matchingProgress.TargetCount; + characterProgress.UpdatedOn = DateTime.UtcNow; + + await db.Updateable(characterProgress).ExecuteCommandAsync(); + + // 检查任务是否全部完成 + var allProgresses = await db.Queryable() + .Where(x => x.CharacterId == characterId && x.MissionId == dailyMission.MissionId) + .ToListAsync(); + + bool allCompleted = allProgresses.All(p => p.IsCompleted); + + if (allCompleted) + { + dailyMission.Status = DailyMissionStatus.Completed; + await db.Updateable(dailyMission).ExecuteCommandAsync(); + anyCompleted = true; + } + } + + return (true, anyCompleted); + } } } diff --git a/Build_God_Game/.env.development b/Build_God_Game/.env.development index b580ebe..40bd306 100644 --- a/Build_God_Game/.env.development +++ b/Build_God_Game/.env.development @@ -1,2 +1,2 @@ # 开发环境配置 -VITE_API_URL=https://localhost:59447/api/god/ +VITE_API_URL=http://localhost:5091/api/god/ diff --git a/Build_God_Game/src/api/bag.ts b/Build_God_Game/src/api/bag.ts index 71fdb5d..d2a3e28 100644 --- a/Build_God_Game/src/api/bag.ts +++ b/Build_God_Game/src/api/bag.ts @@ -39,4 +39,11 @@ export const getCharacterBag = (characterId: number): Promise => { return http.get(`bag/${characterBagId}/items`) +} + +export const addItemToBag = (characterBagId: number, itemType: number, itemId: number, quantity: number, withMissionProgress: boolean = false): Promise => { + if (withMissionProgress) { + return http.post(`bag/${characterBagId}/items/with-mission`, { itemType, itemId, quantity }) + } + return http.post(`bag/${characterBagId}/items`, { itemType, itemId, quantity }) } \ No newline at end of file diff --git a/Build_God_Game/src/api/dailyMission.ts b/Build_God_Game/src/api/dailyMission.ts index f148739..1eca7a1 100644 --- a/Build_God_Game/src/api/dailyMission.ts +++ b/Build_God_Game/src/api/dailyMission.ts @@ -12,6 +12,25 @@ export const RewardType = { Money: 3 } as const export type RewardType = typeof RewardType[keyof typeof RewardType] +export const MissionType = { + Collection: 1, + Hunting: 2 +} as const +export type MissionType = typeof MissionType[keyof typeof MissionType] +export const MissionDifficulty = { + Normal: 1, + Hard: 2, + Purgatory: 3 +} as const +export type MissionDifficulty = typeof MissionDifficulty[keyof typeof MissionDifficulty] +export const ProgressTargetType = { + CollectItem: 1, + Fish: 2, + KillMonster: 3, + ConsumeItem: 4, + Custom: 5 +} as const +export type ProgressTargetType = typeof ProgressTargetType[keyof typeof ProgressTargetType] export interface MissionReward { rewardType: RewardType rewardTypeName: string @@ -19,6 +38,14 @@ export interface MissionReward { itemName: string count: number } +export interface MissionProgressDto { + missionProgressId: number + targetType: ProgressTargetType + targetItemId: number | null + targetItemName: string | null + targetCount: number + currentCount: number +} export interface DailyMission { id: number characterId: number @@ -36,6 +63,9 @@ export interface DailyMission { todayClaimedCount: number todayTotalCount: number rewards: MissionReward[] + missionType: MissionType + difficulty: MissionDifficulty + progresses: MissionProgressDto[] } export const dailyMissionApi = { getList: (): Promise => { @@ -46,5 +76,13 @@ export const dailyMissionApi = { }, claim: (dailyMissionId: number): Promise => { return http.post(`/dailyMission/${dailyMissionId}/claim`) + }, + updateProgress: (progressType: ProgressTargetType, itemId: number | null, itemName: string | null, count: number): Promise<{ success: boolean; missionCompleted: boolean }> => { + return http.post('/mission/progress/update', { + progressType, + itemId, + itemName, + count + }) } } \ No newline at end of file diff --git a/Build_God_Game/src/assets/images/collection.svg b/Build_God_Game/src/assets/images/collection.svg new file mode 100644 index 0000000..d866031 --- /dev/null +++ b/Build_God_Game/src/assets/images/collection.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Build_God_Game/src/assets/images/hunting.svg b/Build_God_Game/src/assets/images/hunting.svg new file mode 100644 index 0000000..2f45547 --- /dev/null +++ b/Build_God_Game/src/assets/images/hunting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Build_God_Game/src/composables/useMissionProgress.ts b/Build_God_Game/src/composables/useMissionProgress.ts new file mode 100644 index 0000000..26316f6 --- /dev/null +++ b/Build_God_Game/src/composables/useMissionProgress.ts @@ -0,0 +1,42 @@ +import { dailyMissionApi, ProgressTargetType } from '@/api/dailyMission' + +export const useMissionProgress = () => { + const updateProgress = async ( + progressType: ProgressTargetType, + itemId: number | null = null, + itemName: string | null = null, + count: number = 1 + ) => { + try { + const result = await dailyMissionApi.updateProgress(progressType, itemId, itemName, count) + return result + } catch (error) { + console.error('更新任务进度失败:', error) + return null + } + } + + const onCollectItem = async (itemId: number, itemName: string, count: number = 1) => { + return updateProgress(ProgressTargetType.CollectItem, itemId, itemName, count) + } + + const onKillMonster = async (monsterId: number, monsterName: string, count: number = 1) => { + return updateProgress(ProgressTargetType.KillMonster, monsterId, monsterName, count) + } + + const onFish = async (count: number = 1) => { + return updateProgress(ProgressTargetType.Fish, null, '钓鱼', count) + } + + const onConsumeItem = async (itemId: number, itemName: string, count: number = 1) => { + return updateProgress(ProgressTargetType.ConsumeItem, itemId, itemName, count) + } + + return { + updateProgress, + onCollectItem, + onKillMonster, + onFish, + onConsumeItem + } +} diff --git a/Build_God_Game/src/views/DailyMissionView.vue b/Build_God_Game/src/views/DailyMissionView.vue index a4617b4..1ef3128 100644 --- a/Build_God_Game/src/views/DailyMissionView.vue +++ b/Build_God_Game/src/views/DailyMissionView.vue @@ -1,30 +1,14 @@