mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2026-03-05 06:55:26 +00:00
refactor(selector): simplify presets with data-driven groups
This commit is contained in:
@@ -86,6 +86,8 @@ const filteredItems = (group: GroupConfig) => {
|
||||
if (group.name !== 'ALL') {
|
||||
if (group.filter) {
|
||||
items = items.filter(group.filter)
|
||||
} else if (!props.config.groupField) {
|
||||
items = []
|
||||
} else {
|
||||
items = items.filter(item =>
|
||||
item[props.config.groupField]?.toLowerCase() === group.name.toLowerCase()
|
||||
|
||||
@@ -3,6 +3,7 @@ import { computed } from 'vue';
|
||||
import { useDialogs } from '@/ts/useDialogs';
|
||||
import { getLogicFlowInstance } from '@/ts/useLogicFlow';
|
||||
import { SELECTOR_PRESETS } from '@/configs/selectorPresets';
|
||||
import type { SelectorConfig } from '@/types/selector';
|
||||
|
||||
const props = defineProps<{
|
||||
node: any;
|
||||
@@ -10,30 +11,29 @@ const props = defineProps<{
|
||||
|
||||
const { openGenericSelector } = useDialogs();
|
||||
|
||||
// 当前选中的资产库
|
||||
const currentLibrary = computed(() => props.node.properties?.assetLibrary || 'shikigami');
|
||||
|
||||
// 当前选中的资产
|
||||
const currentAsset = computed(() => {
|
||||
return props.node.properties?.selectedAsset || { name: '未选择' };
|
||||
});
|
||||
|
||||
// 打开选择器
|
||||
const handleOpenSelector = () => {
|
||||
const lf = getLogicFlowInstance();
|
||||
const node = props.node;
|
||||
if (!lf || !node) return;
|
||||
|
||||
const library = currentLibrary.value;
|
||||
const config = SELECTOR_PRESETS[library];
|
||||
const preset = SELECTOR_PRESETS[library];
|
||||
|
||||
if (!config) {
|
||||
if (!preset) {
|
||||
console.error('未找到资产库配置:', library);
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置当前选中项
|
||||
config.currentItem = node.properties?.selectedAsset;
|
||||
const config: SelectorConfig = {
|
||||
...preset,
|
||||
currentItem: node.properties?.selectedAsset || null
|
||||
};
|
||||
|
||||
openGenericSelector(config, (selectedItem) => {
|
||||
lf.setProperties(node.id, {
|
||||
@@ -80,4 +80,4 @@ const handleOpenSelector = () => {
|
||||
color: #606266;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -3,7 +3,7 @@
|
||||
* 定义各种资产类型的选择器配置
|
||||
*/
|
||||
|
||||
import type { SelectorConfig } from '@/types/selector'
|
||||
import type { GroupConfig, SelectorConfig } from '@/types/selector'
|
||||
import shikigamiData from '@/data/Shikigami.json'
|
||||
import yuhunData from '@/data/Yuhun.json'
|
||||
|
||||
@@ -13,8 +13,8 @@ const onmyojiData = [
|
||||
{ id: '11', name: '神乐', avatar: '/assets/downloaded_images/hero_11_11.png' },
|
||||
{ id: '12', name: '八百比丘尼', avatar: '/assets/downloaded_images/hero_12_12.png' },
|
||||
{ id: '13', name: '源博雅', avatar: '/assets/downloaded_images/hero_13_13.png' },
|
||||
{ id: '15', name: '不知火', avatar: '/assets/downloaded_images/hero_15_15.png' },
|
||||
{ id: '16', name: '鬼灯', avatar: '/assets/downloaded_images/hero_16_16.png' }
|
||||
{ id: '15', name: '源赖光', avatar: '/assets/downloaded_images/hero_15_15.png' },
|
||||
{ id: '16', name: '藤原道长', avatar: '/assets/downloaded_images/hero_16_16.png' }
|
||||
]
|
||||
|
||||
// 阴阳师技能数据
|
||||
@@ -59,25 +59,89 @@ const onmyojiSkillData = [
|
||||
{ onmyojiId: '13', onmyojiName: '源博雅', skillId: '9032', name: '通用技能2', avatar: '/assets/downloaded_images/hero_13_skill_9032.png' },
|
||||
{ onmyojiId: '13', onmyojiName: '源博雅', skillId: '9033', name: '通用技能3', avatar: '/assets/downloaded_images/hero_13_skill_9033.png' },
|
||||
|
||||
// 不知火的技能
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1501', name: '技能1', avatar: '/assets/downloaded_images/hero_15_skill_1501.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1502', name: '技能2', avatar: '/assets/downloaded_images/hero_15_skill_1502.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1503', name: '技能3', avatar: '/assets/downloaded_images/hero_15_skill_1503.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1504', name: '技能4', avatar: '/assets/downloaded_images/hero_15_skill_1504.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1505', name: '技能5', avatar: '/assets/downloaded_images/hero_15_skill_1505.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1506', name: '技能6', avatar: '/assets/downloaded_images/hero_15_skill_1506.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1507', name: '技能7', avatar: '/assets/downloaded_images/hero_15_skill_1507.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '不知火', skillId: '1508', name: '技能8', avatar: '/assets/downloaded_images/hero_15_skill_1508.png' },
|
||||
// 源赖光的技能
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1501', name: '技能1', avatar: '/assets/downloaded_images/hero_15_skill_1501.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1502', name: '技能2', avatar: '/assets/downloaded_images/hero_15_skill_1502.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1503', name: '技能3', avatar: '/assets/downloaded_images/hero_15_skill_1503.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1504', name: '技能4', avatar: '/assets/downloaded_images/hero_15_skill_1504.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1505', name: '技能5', avatar: '/assets/downloaded_images/hero_15_skill_1505.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1506', name: '技能6', avatar: '/assets/downloaded_images/hero_15_skill_1506.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1507', name: '技能7', avatar: '/assets/downloaded_images/hero_15_skill_1507.png' },
|
||||
{ onmyojiId: '15', onmyojiName: '源赖光', skillId: '1508', name: '技能8', avatar: '/assets/downloaded_images/hero_15_skill_1508.png' },
|
||||
|
||||
// 鬼灯的技能
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1601', name: '技能1', avatar: '/assets/downloaded_images/hero_16_skill_1601.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1602', name: '技能2', avatar: '/assets/downloaded_images/hero_16_skill_1602.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1603', name: '技能3', avatar: '/assets/downloaded_images/hero_16_skill_1603.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1604', name: '技能4', avatar: '/assets/downloaded_images/hero_16_skill_1604.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1605', name: '技能5', avatar: '/assets/downloaded_images/hero_16_skill_1605.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1606', name: '技能6', avatar: '/assets/downloaded_images/hero_16_skill_1606.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1607', name: '技能7', avatar: '/assets/downloaded_images/hero_16_skill_1607.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '鬼灯', skillId: '1608', name: '技能8', avatar: '/assets/downloaded_images/hero_16_skill_1608.png' }
|
||||
// 藤原道长的技能
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1601', name: '技能1', avatar: '/assets/downloaded_images/hero_16_skill_1601.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1602', name: '技能2', avatar: '/assets/downloaded_images/hero_16_skill_1602.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1603', name: '技能3', avatar: '/assets/downloaded_images/hero_16_skill_1603.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1604', name: '技能4', avatar: '/assets/downloaded_images/hero_16_skill_1604.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1605', name: '技能5', avatar: '/assets/downloaded_images/hero_16_skill_1605.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1606', name: '技能6', avatar: '/assets/downloaded_images/hero_16_skill_1606.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1607', name: '技能7', avatar: '/assets/downloaded_images/hero_16_skill_1607.png' },
|
||||
{ onmyojiId: '16', onmyojiName: '藤原道长', skillId: '1608', name: '技能8', avatar: '/assets/downloaded_images/hero_16_skill_1608.png' }
|
||||
]
|
||||
|
||||
const ALL_GROUP: GroupConfig = { label: '\u5168\u90e8', name: 'ALL' }
|
||||
|
||||
const buildGroupsFromField = (
|
||||
dataSource: Array<Record<string, any>>,
|
||||
field: string,
|
||||
options?: {
|
||||
order?: string[]
|
||||
labelMap?: Record<string, string>
|
||||
}
|
||||
): GroupConfig[] => {
|
||||
const raw = new Set<string>()
|
||||
dataSource.forEach((item) => {
|
||||
const value = item?.[field]
|
||||
if (value != null && String(value).trim()) {
|
||||
raw.add(String(value))
|
||||
}
|
||||
})
|
||||
|
||||
const values = Array.from(raw)
|
||||
const order = options?.order ?? []
|
||||
const ordered = [
|
||||
...order.filter((value) => values.includes(value)),
|
||||
...values.filter((value) => !order.includes(value)).sort((a, b) => a.localeCompare(b))
|
||||
]
|
||||
|
||||
return [
|
||||
ALL_GROUP,
|
||||
...ordered.map((value) => ({
|
||||
label: options?.labelMap?.[value] ?? value,
|
||||
name: value
|
||||
}))
|
||||
]
|
||||
}
|
||||
|
||||
const shikigamiGroups = buildGroupsFromField(shikigamiData as any[], 'rarity', {
|
||||
order: ['UR', 'SP', 'SSR', 'SR', 'R', 'N', 'L', 'G'],
|
||||
labelMap: {
|
||||
L: '\u8054\u52a8',
|
||||
G: '\u5451\u592a'
|
||||
}
|
||||
})
|
||||
|
||||
const yuhunGroups = buildGroupsFromField(yuhunData as any[], 'type', {
|
||||
order: ['attack', 'Crit', 'Health', 'Defense', 'ControlHit', 'ControlMiss', 'PVE', 'CritDamage'],
|
||||
labelMap: {
|
||||
attack: '\u653b\u51fb\u7c7b',
|
||||
Crit: '\u66b4\u51fb\u7c7b',
|
||||
Health: '\u751f\u547d\u7c7b',
|
||||
Defense: '\u9632\u5fa1\u7c7b',
|
||||
ControlHit: '\u6548\u679c\u547d\u4e2d',
|
||||
ControlMiss: '\u6548\u679c\u62b5\u6297',
|
||||
PVE: 'PVE',
|
||||
CritDamage: '\u66b4\u51fb\u4f24\u5bb3'
|
||||
}
|
||||
})
|
||||
|
||||
const onmyojiSkillGroups = [
|
||||
ALL_GROUP,
|
||||
...onmyojiData.map((item) => ({
|
||||
label: item.name,
|
||||
name: item.name
|
||||
}))
|
||||
]
|
||||
|
||||
export const SELECTOR_PRESETS: Record<string, SelectorConfig> = {
|
||||
@@ -85,17 +149,7 @@ export const SELECTOR_PRESETS: Record<string, SelectorConfig> = {
|
||||
title: '请选择式神',
|
||||
dataSource: shikigamiData,
|
||||
groupField: 'rarity',
|
||||
groups: [
|
||||
{ label: '全部', name: 'ALL' },
|
||||
{ label: 'UR', name: 'UR' },
|
||||
{ label: 'SP', name: 'SP' },
|
||||
{ label: 'SSR', name: 'SSR' },
|
||||
{ label: 'SR', name: 'SR' },
|
||||
{ label: 'R', name: 'R' },
|
||||
{ label: 'N', name: 'N' },
|
||||
{ label: '联动', name: 'L' },
|
||||
{ label: '呱太', name: 'G' }
|
||||
],
|
||||
groups: shikigamiGroups,
|
||||
itemRender: {
|
||||
imageField: 'avatar',
|
||||
labelField: 'name'
|
||||
@@ -106,16 +160,7 @@ export const SELECTOR_PRESETS: Record<string, SelectorConfig> = {
|
||||
title: '请选择御魂',
|
||||
dataSource: yuhunData,
|
||||
groupField: 'type',
|
||||
groups: [
|
||||
{ label: '全部', name: 'ALL' },
|
||||
{ label: '攻击类', name: 'attack' },
|
||||
{ label: '暴击类', name: 'Crit' },
|
||||
{ label: '生命类', name: 'Health' },
|
||||
{ label: '防御类', name: 'Defense' },
|
||||
{ label: '效果命中', name: 'Effect' },
|
||||
{ label: '效果抵抗', name: 'EffectResist' },
|
||||
{ label: '特殊类', name: 'Special' }
|
||||
],
|
||||
groups: yuhunGroups,
|
||||
itemRender: {
|
||||
imageField: 'avatar',
|
||||
labelField: 'name'
|
||||
@@ -126,9 +171,7 @@ export const SELECTOR_PRESETS: Record<string, SelectorConfig> = {
|
||||
title: '请选择阴阳师',
|
||||
dataSource: onmyojiData,
|
||||
groupField: null,
|
||||
groups: [
|
||||
{ label: '全部', name: 'ALL' }
|
||||
],
|
||||
groups: [ALL_GROUP],
|
||||
itemRender: {
|
||||
imageField: 'avatar',
|
||||
labelField: 'name'
|
||||
@@ -139,15 +182,7 @@ export const SELECTOR_PRESETS: Record<string, SelectorConfig> = {
|
||||
title: '请选择阴阳师技能',
|
||||
dataSource: onmyojiSkillData,
|
||||
groupField: 'onmyojiName',
|
||||
groups: [
|
||||
{ label: '全部', name: 'ALL' },
|
||||
{ label: '晴明', name: '晴明' },
|
||||
{ label: '神乐', name: '神乐' },
|
||||
{ label: '八百比丘尼', name: '八百比丘尼' },
|
||||
{ label: '源博雅', name: '源博雅' },
|
||||
{ label: '不知火', name: '不知火' },
|
||||
{ label: '鬼灯', name: '鬼灯' }
|
||||
],
|
||||
groups: onmyojiSkillGroups,
|
||||
itemRender: {
|
||||
imageField: 'avatar',
|
||||
labelField: 'name'
|
||||
|
||||
@@ -1,34 +1,23 @@
|
||||
/**
|
||||
* 通用选择器配置接口
|
||||
* 用于配置驱动的图片选择器组件
|
||||
*/
|
||||
export interface GroupConfig<T = any> {
|
||||
label: string
|
||||
name: string
|
||||
filter?: (item: T) => boolean
|
||||
}
|
||||
|
||||
export interface GroupConfig {
|
||||
label: string // Tab显示标签
|
||||
name: string // Tab标识符
|
||||
filter?: (item: any) => boolean // 自定义过滤函数(可选)
|
||||
export interface SelectorItemRender {
|
||||
imageField: string
|
||||
labelField: string
|
||||
imageSize?: number
|
||||
}
|
||||
|
||||
export interface SelectorConfig<T = any> {
|
||||
// 基础配置
|
||||
title: string // 对话框标题
|
||||
dataSource: T[] // 数据源
|
||||
groupField: string // 分组字段名 (如 'rarity', 'type')
|
||||
|
||||
// 分组配置
|
||||
groups: GroupConfig[] // Tab分组配置
|
||||
|
||||
// 展示配置
|
||||
itemRender: {
|
||||
imageField: string // 图片字段名 (如 'avatar')
|
||||
labelField: string // 标签字段名 (如 'name')
|
||||
imageSize?: number // 图片尺寸,默认100px
|
||||
}
|
||||
|
||||
// 搜索配置
|
||||
searchable?: boolean // 是否启用搜索,默认true
|
||||
searchFields?: string[] // 搜索字段,默认使用labelField
|
||||
|
||||
// 当前选中项
|
||||
currentItem?: T
|
||||
}
|
||||
title: string
|
||||
dataSource: T[]
|
||||
// Some selector data sources only use ALL tab, so this can be null/undefined.
|
||||
groupField?: string | null
|
||||
groups: GroupConfig<T>[]
|
||||
itemRender: SelectorItemRender
|
||||
searchable?: boolean
|
||||
searchFields?: string[]
|
||||
currentItem?: T | null
|
||||
}
|
||||
Reference in New Issue
Block a user