diff --git a/Build_God_Admin_Frontend/Frontend/src/api/monster.ts b/Build_God_Admin_Frontend/Frontend/src/api/monster.ts index 0150948..479e828 100644 --- a/Build_God_Admin_Frontend/Frontend/src/api/monster.ts +++ b/Build_God_Admin_Frontend/Frontend/src/api/monster.ts @@ -1,17 +1,34 @@ import http, { type EnumInfoDto } from "@/api/index"; +export interface MonsterEquipmentRow { + equipmentTemplateId: number; + attributes: string; +} + +export interface MonsterEquipmentDto { + id: number; + monsterId: number; + equipmentTemplateId: number; + attributes: string; + equipmentTemplateName?: string; +} + export interface Monster { id: number; name: string; description: string; + configuredExp: number; + professionId?: number | null; + levelId: number; + type: number; + icon?: string; + /** 计算后的展示属性 */ health: number; attack: number; defense: number; criticalRate: number; - levelId: number; - type: number; - icon?: string; rewards?: MonsterReward[]; + equipment?: MonsterEquipmentDto[]; } export interface MonsterReward { @@ -33,20 +50,32 @@ interface SearchMonsterDto { pageNumber: number | undefined; pageSize: number | undefined; monsterType: number | undefined; - level: number | undefined; + levelId: number | undefined; +} + +export interface MonsterSavePayload { + id: number; + name: string; + description: string; + configuredExp: number; + professionId?: number | null; + levelId: number; + type: number; + icon?: string; + equipment: MonsterEquipmentRow[]; } export const GetMonsterList = ( monsterType?: number, - level?: number, + levelId?: number, pageNumber?: number, pageSize?: number ): Promise | Monster[]> => { - var dto: SearchMonsterDto = { + const dto: SearchMonsterDto = { pageNumber: pageNumber, pageSize: pageSize, monsterType: monsterType, - level: level, + levelId: levelId, }; return http.post("/monster/all", dto); }; @@ -55,11 +84,12 @@ export const GetMonsterById = (id: number): Promise => { return http.get(`/monster/${id}`); }; -export const AddMonster = (data: Monster): Promise => { - return http.post("/monster", data); +export const AddMonster = (data: MonsterSavePayload): Promise => { + const { id: _id, ...body } = data; + return http.post("/monster", body); }; -export const UpdateMonster = (data: Monster): Promise => { +export const UpdateMonster = (data: MonsterSavePayload): Promise => { return http.put(`/monster/${data.id}`, data); }; diff --git a/Build_God_Admin_Frontend/Frontend/src/views/admin/MonstersView.vue b/Build_God_Admin_Frontend/Frontend/src/views/admin/MonstersView.vue index 2817321..9e7368e 100644 --- a/Build_God_Admin_Frontend/Frontend/src/views/admin/MonstersView.vue +++ b/Build_God_Admin_Frontend/Frontend/src/views/admin/MonstersView.vue @@ -9,6 +9,8 @@ import { UpdateMonster, type Monster, type MonsterReward, + type MonsterEquipmentRow, + type MonsterSavePayload, GetRewardTypes, AddMonsterReward, UpdateMonsterReward, @@ -21,6 +23,7 @@ import { GetEquipmentTemplateList, type EquipmentTemplate } from '@/api/equipmen import { Plus, Edit, Delete, Close } from '@element-plus/icons-vue' import { ICONS } from '@/constants/theme' import { GetLevelList, type Level } from '@/api/level' +import { GetProfessionList, type Profession } from '@/api/spirit' const monsters = ref([]) @@ -28,8 +31,8 @@ const monsterTypes = ref([]) const rewardTypes = ref([]) const pillData = ref([]) const equipmentData = ref([]) -//等级 const levels = ref([]) +const professions = ref([]) const currentPage = ref(1) const pageSize = ref(10) @@ -59,19 +62,26 @@ const monsterIconOptions = [ { value: '猪.svg', label: '猪' } ] -const formData = ref({ +type MonsterFormData = Omit & { equipment: MonsterEquipmentRow[] } + +const defaultMonsterForm = (): MonsterFormData => ({ id: 0, name: '', description: '', + configuredExp: 0, + professionId: undefined, + levelId: 1, + type: 1, + icon: '', health: 0, attack: 0, defense: 0, criticalRate: 0, - levelId: 1, - type: 1, - icon: '' + equipment: [] }) +const formData = ref(defaultMonsterForm()) + const rewardFormData = ref({ id: 0, monsterId: 0, @@ -95,8 +105,7 @@ const translateMonsterType = (typeId: number) => { } const translateLevel = (id: number) => { - console.log(levels) - var item = levels.value.find(x => x.levelId == id); + const item = levels.value.find(x => x.levelId == id) if (item) { return item.name } @@ -116,28 +125,46 @@ const getMonsterTypeClass = (typeId: number) => { } } -const openDialog = (monster?: Monster) => { +const openDialog = async (monster?: Monster) => { + if (!equipmentData.value.length) { + const eqs = await fetchEquipments() + equipmentData.value = eqs + } + if (!professions.value.length) { + try { + professions.value = await GetProfessionList() + } catch { + professions.value = [] + } + } if (monster !== undefined) { isEditing.value = true - formData.value = { ...monster } - } else { - isEditing.value = false formData.value = { - id: 0, - name: '', - description: '', - health: 0, - attack: 0, - defense: 0, - criticalRate: 0, - levelId: 1, - type: 1, - icon: '' + ...monster, + equipment: (monster.equipment || []).map(e => ({ + equipmentTemplateId: e.equipmentTemplateId, + attributes: e.attributes || '[]' + })) } + } else { + isEditing.value = false + formData.value = defaultMonsterForm() } showDialog.value = true } +const addEquipmentRow = () => { + const firstId = equipmentData.value[0]?.id ?? 0 + formData.value.equipment.push({ + equipmentTemplateId: firstId, + attributes: '[]' + }) +} + +const removeEquipmentRow = (index: number) => { + formData.value.equipment.splice(index, 1) +} + const closeDialog = () => { showDialog.value = false } @@ -268,6 +295,21 @@ const formatRewardDisplay = (r: MonsterReward) => { return r.itemName ? `${r.itemName} ×${r.count}` : `×${r.count}` } +const buildSavePayload = (): MonsterSavePayload => ({ + id: formData.value.id, + name: formData.value.name, + description: formData.value.description, + configuredExp: formData.value.configuredExp, + professionId: formData.value.professionId ?? null, + levelId: formData.value.levelId, + type: formData.value.type, + icon: formData.value.icon, + equipment: formData.value.equipment.map(e => ({ + equipmentTemplateId: e.equipmentTemplateId, + attributes: (e.attributes || '').trim() || '[]' + })) +}) + const saveMonster = async () => { if (formData.value.name == undefined || formData.value.description == undefined @@ -278,8 +320,10 @@ const saveMonster = async () => { return } + const payload = buildSavePayload() + if (isEditing.value) { - var result = await UpdateMonster(formData.value) + var result = await UpdateMonster(payload) if (result) { ElMessage.success('怪兽更新成功') closeDialog() @@ -288,7 +332,7 @@ const saveMonster = async () => { ElMessage.error('怪兽更新失败') } } else { - var result = await AddMonster(formData.value) + var result = await AddMonster(payload) if (result) { ElMessage.success('怪兽添加成功') closeDialog() @@ -423,13 +467,14 @@ const fetchLevels = async () => { - + +