refactor: 重构属性编辑面板,支持Tab分离和节点类型切换

- 将属性面板分为游戏属性和图像属性两个Tab
- 游戏属性Tab包含节点基本信息、类型切换和特定属性
- 图像属性Tab包含所有样式设置(填充、描边、阴影等)
- 资产选择器节点支持在式神和御魂之间切换
- 切换节点类型时自动清空已选资产
- 优化AssetSelectorPanel,移除重复的资产库选择器
This commit is contained in:
2026-02-14 21:50:51 +08:00
parent bbcc1f6980
commit 4a4a55110b
15 changed files with 1069 additions and 26 deletions

View File

@@ -0,0 +1,114 @@
<template>
<el-dialog
v-model="show"
:title="config.title"
>
<span v-if="config.currentItem">
当前选择{{ config.currentItem[config.itemRender.labelField] }}
</span>
<!-- 搜索框 -->
<div v-if="config.searchable !== false" style="display: flex; align-items: center;">
<el-input
v-model="searchText"
placeholder="请输入内容"
style="width: 200px; margin-right: 10px;"
/>
</div>
<!-- Tab分组 -->
<el-tabs
v-model="activeTab"
type="card"
class="demo-tabs"
>
<el-tab-pane
v-for="group in config.groups"
:key="group.name"
:label="group.label"
:name="group.name"
>
<div style="max-height: 600px; overflow-y: auto;">
<el-space wrap size="large">
<div
v-for="item in filteredItems(group)"
:key="item[config.itemRender.labelField]"
style="display: flex; flex-direction: column; justify-content: center"
>
<el-button
:style="`width: ${imageSize}px; height: ${imageSize}px;`"
@click="handleSelect(item)"
>
<img
:src="item[config.itemRender.imageField]"
:style="`width: ${imageSize - 1}px; height: ${imageSize - 1}px;`"
>
</el-button>
<span style="text-align: center; display: block;">
{{ item[config.itemRender.labelField] }}
</span>
</div>
</el-space>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { SelectorConfig, GroupConfig } from '@/types/selector'
const props = defineProps<{
config: SelectorConfig
modelValue: boolean
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'select': [item: any]
}>()
const show = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
const searchText = ref('')
const activeTab = ref('ALL')
const imageSize = computed(() => props.config.itemRender.imageSize || 100)
// 过滤逻辑
const filteredItems = (group: GroupConfig) => {
let items = props.config.dataSource
// 分组过滤
if (group.name !== 'ALL') {
if (group.filter) {
items = items.filter(group.filter)
} else {
items = items.filter(item =>
item[props.config.groupField]?.toLowerCase() === group.name.toLowerCase()
)
}
}
// 搜索过滤
if (searchText.value.trim()) {
const searchFields = props.config.searchFields || [props.config.itemRender.labelField]
items = items.filter(item =>
searchFields.some(field =>
item[field]?.toLowerCase().includes(searchText.value.toLowerCase())
)
)
}
return items
}
const handleSelect = (item: any) => {
emit('select', item)
searchText.value = ''
activeTab.value = 'ALL'
}
</script>