feat(home-page): add hero sorting function
1. 新增首页工具栏排序控件,支持按职业/星级排序及升降序切换 2. 实现排序逻辑,保留原始数组下标保证编辑定位准确 3. 更新样式文件,添加排序控件组的布局样式
This commit is contained in:
@@ -13,11 +13,22 @@
|
|||||||
<!-- 首页:英雄卡片列表 -->
|
<!-- 首页:英雄卡片列表 -->
|
||||||
<div class="home-toolbar">
|
<div class="home-toolbar">
|
||||||
<span class="muted">共 {{ heroes.length }} 个英雄</span>
|
<span class="muted">共 {{ heroes.length }} 个英雄</span>
|
||||||
|
<div class="toolbar-sort">
|
||||||
|
<el-radio-group v-model="sortKey" size="small">
|
||||||
|
<el-radio-button value="none">默认</el-radio-button>
|
||||||
|
<el-radio-button value="role">按职业</el-radio-button>
|
||||||
|
<el-radio-button value="rarity">按星级</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
<el-radio-group v-if="sortKey !== 'none'" v-model="sortOrder" size="small">
|
||||||
|
<el-radio-button value="asc">升序</el-radio-button>
|
||||||
|
<el-radio-button value="desc">降序</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
<el-button size="small" type="primary" @click="addHero">+ 新建英雄</el-button>
|
<el-button size="small" type="primary" @click="addHero">+ 新建英雄</el-button>
|
||||||
</div>
|
</div>
|
||||||
<section class="hero-rows">
|
<section class="hero-rows">
|
||||||
<div v-if="!heroes.length" class="empty">暂无英雄,点击右上角「新建英雄」开始配置</div>
|
<div v-if="!heroes.length" class="empty">暂无英雄,点击右上角「新建英雄」开始配置</div>
|
||||||
<div v-for="(h, i) in heroes" :key="h.uuid" class="hero-row" @click="openEdit(i)">
|
<div v-for="{ h, i } in sortedHeroes" :key="h.uuid" class="hero-row" @click="openEdit(i)">
|
||||||
<div class="row-main">
|
<div class="row-main">
|
||||||
<span class="row-uuid">{{ h.uuid }}</span>
|
<span class="row-uuid">{{ h.uuid }}</span>
|
||||||
<span class="row-name">{{ h.name || '(未命名)' }}</span>
|
<span class="row-name">{{ h.name || '(未命名)' }}</span>
|
||||||
@@ -178,7 +189,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, watch, onMounted } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { api } from './api'
|
import { api } from './api'
|
||||||
import {
|
import {
|
||||||
@@ -200,6 +211,28 @@ const editVisible = ref(false)
|
|||||||
|
|
||||||
const current = computed(() => heroes.value[activeIdx.value])
|
const current = computed(() => heroes.value[activeIdx.value])
|
||||||
|
|
||||||
|
// 首页列表排序:none 原始顺序 / role 按职业枚举序(坦克→辅助)/ rarity 按星级
|
||||||
|
const sortKey = ref('none')
|
||||||
|
const sortOrder = ref('desc')
|
||||||
|
// 切换排序维度时重置方向:职业升序直观(坦克在前),星级降序直观(高星在前)
|
||||||
|
watch(sortKey, (k) => { sortOrder.value = k === 'role' ? 'asc' : 'desc' })
|
||||||
|
|
||||||
|
// 排序视图:携带原始下标,保证点击卡片仍能定位到 heroes 中的编辑对象,且不改写保存顺序
|
||||||
|
const sortedHeroes = computed(() => {
|
||||||
|
const list = heroes.value.map((h, i) => ({ h, i }))
|
||||||
|
if (sortKey.value === 'none') return list
|
||||||
|
const dir = sortOrder.value === 'asc' ? 1 : -1
|
||||||
|
const roleIdx = (key) => HERO_ROLES.findIndex((r) => r.key === key)
|
||||||
|
list.sort((a, b) => {
|
||||||
|
const d = sortKey.value === 'role'
|
||||||
|
? roleIdx(a.h.roleKey) - roleIdx(b.h.roleKey)
|
||||||
|
: (a.h.rarity || 0) - (b.h.rarity || 0)
|
||||||
|
// 同维度内按 uuid 升序兜底,保证排序稳定
|
||||||
|
return d !== 0 ? d * dir : a.h.uuid - b.h.uuid
|
||||||
|
})
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
const skillMap = computed(() => meta.value?.SkillSet || {})
|
const skillMap = computed(() => meta.value?.SkillSet || {})
|
||||||
const allSkills = computed(() => Object.values(skillMap.value).sort((a, b) => a.uuid - b.uuid))
|
const allSkills = computed(() => Object.values(skillMap.value).sort((a, b) => a.uuid - b.uuid))
|
||||||
const fieldOptions = computed(() => Object.values(meta.value?.FieldSkillSet || {}).sort((a, b) => a.uuid - b.uuid))
|
const fieldOptions = computed(() => Object.values(meta.value?.FieldSkillSet || {}).sort((a, b) => a.uuid - b.uuid))
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 首页工具栏:计数 + 新建入口 */
|
/* 首页工具栏:计数 + 排序 + 新建入口 */
|
||||||
.home-toolbar {
|
.home-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
@@ -71,6 +71,8 @@ body {
|
|||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
/* 排序控件组:维度 + 方向 */
|
||||||
|
.toolbar-sort { display: flex; align-items: center; gap: 8px; }
|
||||||
|
|
||||||
/* 首页:一行一个英雄的列表布局 */
|
/* 首页:一行一个英雄的列表布局 */
|
||||||
.hero-rows {
|
.hero-rows {
|
||||||
|
|||||||
Reference in New Issue
Block a user