|
|
|
@ -1,7 +1,7 @@ |
|
|
|
<script setup lang="ts"> |
|
|
|
import { ref, computed, onMounted } from 'vue' |
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus' |
|
|
|
import { AddEquipmentTemplate, DeleteEquipmentTemplate, GetEquipmentTemplateList, GetEquipmentRarities, GetEquipmentTypes, GetEquipmentAttributeTypes, UpdateEquipmentTemplate, type EquipmentTemplate, type EquipmentAttributePool } from '@/api/equipment' |
|
|
|
import { AddEquipmentTemplate, DeleteEquipmentTemplate, GetEquipmentTemplateList, GetEquipmentRarities, GetEquipmentTypes, GetEquipmentAttributeTypes, UpdateEquipmentTemplate, type EquipmentTemplate, type EquipmentAttribute } from '@/api/equipment' |
|
|
|
import type { EnumInfoDto } from '@/api' |
|
|
|
import { GetLevelList, type Level } from '@/api/level' |
|
|
|
import { Plus, Edit, Delete, Close } from '@element-plus/icons-vue' |
|
|
|
@ -37,13 +37,12 @@ const formData = ref<Partial<EquipmentTemplate>>({ |
|
|
|
rarity: 0, |
|
|
|
requirdLevelId: 0, |
|
|
|
setId: null, |
|
|
|
attributePool: '[]', |
|
|
|
randomAttrCount: 4, |
|
|
|
defaultAttributes: '[]', |
|
|
|
maxEnhanceLevel: 10, |
|
|
|
icon: null |
|
|
|
}) |
|
|
|
|
|
|
|
const attributePoolList = ref<EquipmentAttributePool[]>([]) |
|
|
|
const fixedAttrsList = ref<EquipmentAttribute[]>([]) |
|
|
|
|
|
|
|
const filteredEquipments = computed(() => { |
|
|
|
return equipmentTemplates.value.filter(eq => |
|
|
|
@ -70,28 +69,25 @@ const translateLevel = (levelId: number) => { |
|
|
|
return item ? item.name : '未知'; |
|
|
|
} |
|
|
|
|
|
|
|
const addAttributePool = () => { |
|
|
|
attributePoolList.value.push({ |
|
|
|
type: 1, |
|
|
|
min: 0, |
|
|
|
max: 100, |
|
|
|
weight: 1 |
|
|
|
}) |
|
|
|
updateAttributePool() |
|
|
|
const addFixedAttr = () => { |
|
|
|
fixedAttrsList.value.push({ type: 1, value: 0 }) |
|
|
|
updateDefaultAttributes() |
|
|
|
} |
|
|
|
|
|
|
|
const removeAttributePool = (index: number) => { |
|
|
|
attributePoolList.value.splice(index, 1) |
|
|
|
updateAttributePool() |
|
|
|
const removeFixedAttr = (index: number) => { |
|
|
|
fixedAttrsList.value.splice(index, 1) |
|
|
|
updateDefaultAttributes() |
|
|
|
} |
|
|
|
|
|
|
|
const updateAttributePool = () => { |
|
|
|
formData.value.attributePool = JSON.stringify(attributePoolList.value) |
|
|
|
const updateDefaultAttributes = () => { |
|
|
|
formData.value.defaultAttributes = JSON.stringify(fixedAttrsList.value) |
|
|
|
} |
|
|
|
|
|
|
|
const parseAttributePool = (json: string) => { |
|
|
|
const parseDefaultAttributes = (json: string | undefined | null) => { |
|
|
|
if (!json || json === '[]') return [] |
|
|
|
try { |
|
|
|
return JSON.parse(json) as EquipmentAttributePool[] |
|
|
|
const arr = JSON.parse(json) as EquipmentAttribute[] |
|
|
|
return Array.isArray(arr) ? arr.map(x => ({ type: Number(x.type), value: Number(x.value) })) : [] |
|
|
|
} catch { |
|
|
|
return [] |
|
|
|
} |
|
|
|
@ -101,7 +97,7 @@ const openDialog = (eq?: EquipmentTemplate) => { |
|
|
|
if (eq != undefined) { |
|
|
|
isEditing.value = true |
|
|
|
formData.value = { ...eq } |
|
|
|
attributePoolList.value = parseAttributePool(eq.attributePool || '[]') |
|
|
|
fixedAttrsList.value = parseDefaultAttributes(eq.defaultAttributes ?? '[]') |
|
|
|
} else { |
|
|
|
isEditing.value = false |
|
|
|
formData.value = { |
|
|
|
@ -111,13 +107,13 @@ const openDialog = (eq?: EquipmentTemplate) => { |
|
|
|
rarity: undefined, |
|
|
|
requirdLevelId: undefined, |
|
|
|
setId: null, |
|
|
|
attributePool: '[]', |
|
|
|
randomAttrCount: 4, |
|
|
|
defaultAttributes: '[]', |
|
|
|
maxEnhanceLevel: 10, |
|
|
|
icon: null |
|
|
|
} |
|
|
|
attributePoolList.value = [] |
|
|
|
fixedAttrsList.value = [] |
|
|
|
} |
|
|
|
updateDefaultAttributes() |
|
|
|
showDialog.value = true |
|
|
|
} |
|
|
|
|
|
|
|
@ -138,7 +134,7 @@ const saveEquipment = async () => { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
updateAttributePool() |
|
|
|
updateDefaultAttributes() |
|
|
|
|
|
|
|
if (isEditing.value) { |
|
|
|
const index = equipmentTemplates.value.findIndex(p => p.id === formData.value.id) |
|
|
|
@ -157,15 +153,14 @@ const saveEquipment = async () => { |
|
|
|
} |
|
|
|
} else { |
|
|
|
const newOne: EquipmentTemplate = { |
|
|
|
id: 1, |
|
|
|
id: 0, |
|
|
|
name: formData.value.name || '', |
|
|
|
description: formData.value.description || '', |
|
|
|
type: formData.value.type || 1, |
|
|
|
rarity: formData.value.rarity || 1, |
|
|
|
requirdLevelId: formData.value.requirdLevelId || 1, |
|
|
|
setId: formData.value.setId ?? null, |
|
|
|
attributePool: formData.value.attributePool || '[]', |
|
|
|
randomAttrCount: formData.value.randomAttrCount || 4, |
|
|
|
defaultAttributes: formData.value.defaultAttributes || '[]', |
|
|
|
maxEnhanceLevel: formData.value.maxEnhanceLevel || 10, |
|
|
|
icon: formData.value.icon || null, |
|
|
|
} |
|
|
|
@ -205,17 +200,11 @@ const getEqTypeClass = (eqType: number) => { |
|
|
|
case 1: |
|
|
|
return 'eqType-weapon' |
|
|
|
case 2: |
|
|
|
return 'eqType-Armor' |
|
|
|
return 'eqType-armor' |
|
|
|
case 3: |
|
|
|
return 'eqType-Helmet' |
|
|
|
case 4: |
|
|
|
return 'eqType-Necklace' |
|
|
|
case 5: |
|
|
|
return 'eqType-Ring' |
|
|
|
case 6: |
|
|
|
return 'eqType-Boots' |
|
|
|
return 'eqType-accessory' |
|
|
|
default: |
|
|
|
return '' |
|
|
|
return 'eqType-unknown' |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -228,8 +217,6 @@ onMounted(async () => { |
|
|
|
}) |
|
|
|
|
|
|
|
const refreshEquipments = async (page?: number) => { |
|
|
|
|
|
|
|
console.log('current-page', page) |
|
|
|
if (page !== undefined) currentPage.value = page |
|
|
|
const res = await GetEquipmentTemplateList(eqFileterType.value, currentPage.value, pageSize.value) |
|
|
|
|
|
|
|
@ -311,7 +298,11 @@ const fetchAttributeTypes = async () => { |
|
|
|
</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="随机属性数" prop="randomAttrCount" width="100"></el-table-column> |
|
|
|
<el-table-column label="固定属性条数" width="110"> |
|
|
|
<template #default="scoped"> |
|
|
|
{{ parseDefaultAttributes(scoped.row.defaultAttributes ?? '[]').length }} |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="最大强化" prop="maxEnhanceLevel" width="100"></el-table-column> |
|
|
|
<el-table-column label="编辑" fixed="right"> |
|
|
|
<template #default="scoped"> |
|
|
|
@ -357,45 +348,31 @@ const fetchAttributeTypes = async () => { |
|
|
|
<el-form-item label="图标文件名"> |
|
|
|
<el-input v-model="formData.icon" placeholder="如: sword.png" clearable /> |
|
|
|
</el-form-item> |
|
|
|
<el-form-item label="随机属性数量"> |
|
|
|
<el-input-number v-model="formData.randomAttrCount" :min="1" :max="10" /> |
|
|
|
</el-form-item> |
|
|
|
<el-form-item label="最大强化等级"> |
|
|
|
<el-input-number v-model="formData.maxEnhanceLevel" :min="1" :max="20" /> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<!-- 属性池配置 --> |
|
|
|
<div class="attribute-pool-section"> |
|
|
|
<div class="pool-header"> |
|
|
|
<span>属性池配置</span> |
|
|
|
<el-button type="primary" size="small" @click="addAttributePool">添加属性</el-button> |
|
|
|
<span>固定属性(与角色装备实例 JSON 一致,购买时写入实例)</span> |
|
|
|
<el-button type="primary" size="small" @click="addFixedAttr">添加一条</el-button> |
|
|
|
</div> |
|
|
|
<el-table :data="attributePoolList" border size="small"> |
|
|
|
<el-table-column label="属性类型" width="350"> |
|
|
|
<el-table :data="fixedAttrsList" border size="small"> |
|
|
|
<el-table-column label="属性类型" min-width="280"> |
|
|
|
<template #default="scoped"> |
|
|
|
<el-select v-model="scoped.row.type" size="small" @change="updateAttributePool"> |
|
|
|
<el-select v-model="scoped.row.type" size="small" filterable @change="updateDefaultAttributes"> |
|
|
|
<el-option v-for="(value, index) in attributeTypes" :key="index" :value="value.id" :label="value.description"/> |
|
|
|
</el-select> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="最小值" width="150"> |
|
|
|
<el-table-column label="数值" width="180"> |
|
|
|
<template #default="scoped"> |
|
|
|
<el-input-number v-model="scoped.row.min" :min="0" size="small" controls-position="right" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="最大值" width="150"> |
|
|
|
<template #default="scoped"> |
|
|
|
<el-input-number v-model="scoped.row.max" :min="0" size="small" controls-position="right" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="权重" width="150"> |
|
|
|
<template #default="scoped"> |
|
|
|
<el-input-number v-model="scoped.row.weight" :min="1" size="small" controls-position="right" /> |
|
|
|
<el-input-number v-model="scoped.row.value" size="small" controls-position="right" @change="updateDefaultAttributes" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="操作" width="80"> |
|
|
|
<template #default="scoped"> |
|
|
|
<el-button type="danger" size="small" @click="removeAttributePool(scoped.$index)">删除</el-button> |
|
|
|
<el-button type="danger" size="small" @click="removeFixedAttr(scoped.$index)">删除</el-button> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</el-table> |
|
|
|
@ -477,23 +454,11 @@ const fetchAttributeTypes = async () => { |
|
|
|
font-weight: 600; |
|
|
|
} |
|
|
|
|
|
|
|
.eqType-Boots { |
|
|
|
background-color: #7b4ee3; |
|
|
|
} |
|
|
|
|
|
|
|
.eqType-Ring { |
|
|
|
background-color: #b2c522; |
|
|
|
} |
|
|
|
|
|
|
|
.eqType-Necklace { |
|
|
|
background-color: #2281c5; |
|
|
|
.eqType-accessory { |
|
|
|
background-color: #8b5cf6; |
|
|
|
} |
|
|
|
|
|
|
|
.eqType-Helmet { |
|
|
|
background-color: #22c55e; |
|
|
|
} |
|
|
|
|
|
|
|
.eqType-Armor { |
|
|
|
.eqType-armor { |
|
|
|
background-color: #f59e0b; |
|
|
|
} |
|
|
|
|
|
|
|
@ -501,6 +466,10 @@ const fetchAttributeTypes = async () => { |
|
|
|
background-color: #ef4444; |
|
|
|
} |
|
|
|
|
|
|
|
.eqType-unknown { |
|
|
|
background-color: #6b7280; |
|
|
|
} |
|
|
|
|
|
|
|
.actions { |
|
|
|
display: flex; |
|
|
|
gap: 8px; |
|
|
|
|