refactor: clean up
This commit is contained in:
parent
72285e093f
commit
0aaadea2da
|
|
@ -1,7 +1,7 @@
|
|||
import { Show, For } from 'solid-js';
|
||||
import { marked } from '../markdown';
|
||||
import { getLayerStyle } from './utils/dimensions';
|
||||
import {getSelectionBoxStyle, useSelection} from './hooks/use-selection';
|
||||
import {getSelectionBoxStyle, useSelection} from './stores/use-selection';
|
||||
import {DeckStore} from "./stores/deckStore";
|
||||
|
||||
export interface CardPreviewProps {
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
* 属性编辑器 Schema 类型定义
|
||||
*/
|
||||
|
||||
export type FieldType = 'string' | 'number' | 'boolean' | 'text' | 'select';
|
||||
|
||||
export interface FieldSchema {
|
||||
/** 字段名 */
|
||||
key: string;
|
||||
/** 字段类型 */
|
||||
type: FieldType;
|
||||
/** 显示标签 */
|
||||
label?: string;
|
||||
/** 占位符文本 */
|
||||
placeholder?: string;
|
||||
/** 描述/提示文本 */
|
||||
description?: string;
|
||||
/** 是否必需 */
|
||||
required?: boolean;
|
||||
/** 最小值(用于 number 类型) */
|
||||
min?: number;
|
||||
/** 最大值(用于 number 类型) */
|
||||
max?: number;
|
||||
/** 选项(用于 select 类型) */
|
||||
options?: { label: string; value: string }[];
|
||||
/** 行数(用于 text 类型) */
|
||||
rows?: number;
|
||||
/** 默认值 */
|
||||
default?: string | number | boolean;
|
||||
}
|
||||
|
||||
export interface Schema {
|
||||
/** Schema 名称 */
|
||||
name?: string;
|
||||
/** 字段定义列表 */
|
||||
fields: FieldSchema[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 属性值类型
|
||||
*/
|
||||
export type PropertyValues = Record<string, string | number | boolean>;
|
||||
|
||||
/**
|
||||
* usePropertyEditor hook 返回类型
|
||||
*/
|
||||
export interface UsePropertyEditorReturn<T extends PropertyValues> {
|
||||
/** 获取属性值 */
|
||||
get: <K extends keyof T>(key: K) => T[K];
|
||||
/** 设置属性值 */
|
||||
set: <K extends keyof T>(key: K, value: T[K]) => void;
|
||||
/** 获取所有属性值 */
|
||||
getAll: () => T;
|
||||
/** 设置所有属性值 */
|
||||
setAll: (values: T) => void;
|
||||
/** 重置为默认值 */
|
||||
reset: () => void;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { customElement, noShadowDOM } from 'solid-element';
|
||||
import { Show, createEffect, createResource, For } from 'solid-js';
|
||||
import { Show, createEffect, createResource, For, onCleanup } from 'solid-js';
|
||||
import { resolvePath } from './utils/path';
|
||||
import { loadCSV } from './utils/csv-loader';
|
||||
import { initLayerConfigs } from './utils/layer-parser';
|
||||
|
|
@ -7,7 +7,16 @@ import { createDeckStore } from './stores/deckStore';
|
|||
import { CardPreview } from './card-preview';
|
||||
import { DataEditorPanel, PropertiesEditorPanel } from './editor-panel';
|
||||
|
||||
customElement('md-deck', {
|
||||
interface DeckProps {
|
||||
size?: string;
|
||||
grid?: string;
|
||||
bleed?: string;
|
||||
padding?: string;
|
||||
layers?: string;
|
||||
fixed?: boolean | string;
|
||||
}
|
||||
|
||||
customElement<DeckProps>('md-deck', {
|
||||
size: '54x86',
|
||||
grid: '5x8',
|
||||
bleed: '1',
|
||||
|
|
@ -21,7 +30,7 @@ customElement('md-deck', {
|
|||
const store = createDeckStore();
|
||||
|
||||
// 从 element 的 textContent 获取 CSV 路径
|
||||
const src = element?.textContent?.trim() || '';
|
||||
const csvPath = element?.textContent?.trim() || '';
|
||||
|
||||
// 隐藏原始文本内容
|
||||
if (element) {
|
||||
|
|
@ -33,20 +42,37 @@ customElement('md-deck', {
|
|||
const articlePath = articleEl?.getAttribute('data-src') || '';
|
||||
|
||||
// 解析相对路径
|
||||
const resolvedSrc = resolvePath(articlePath, src);
|
||||
const resolvedSrc = resolvePath(articlePath, csvPath);
|
||||
|
||||
// 初始化 store
|
||||
store.initialize(props, src);
|
||||
// 初始化 store 属性
|
||||
store.setSize(props.size || '54x86');
|
||||
store.setGrid(props.grid || '5x8');
|
||||
store.setBleed(props.bleed || '1');
|
||||
store.setPadding(props.padding || '2');
|
||||
|
||||
// 加载 CSV 文件
|
||||
const [csvData] = createResource(() => resolvedSrc, loadCSV);
|
||||
const [csvData, { refetch }] = createResource(() => resolvedSrc, loadCSV);
|
||||
|
||||
// 处理 CSV 数据加载结果
|
||||
createEffect(() => {
|
||||
const data = !csvData.loading && csvData();
|
||||
if (data) {
|
||||
store.setCards(data);
|
||||
store.setLayerConfigs(initLayerConfigs(data, props.layers as string || ''));
|
||||
const data = csvData();
|
||||
const loading = csvData.loading;
|
||||
const error = csvData.error;
|
||||
|
||||
if (error) {
|
||||
store.setError(`加载 CSV 失败:${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!loading && data) {
|
||||
store.loadCards(data);
|
||||
store.setLayerConfigs(initLayerConfigs(data, (props.layers as string) || ''));
|
||||
}
|
||||
});
|
||||
|
||||
// 清理函数
|
||||
onCleanup(() => {
|
||||
// 可以在这里清理资源
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
@ -92,9 +118,30 @@ customElement('md-deck', {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* 错误提示 */}
|
||||
<Show when={store.error}>
|
||||
<div class="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded mb-4">
|
||||
{store.error}
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
{/* 加载状态 */}
|
||||
<Show when={csvData.loading}>
|
||||
<div class="text-center text-gray-500 py-8">
|
||||
加载卡牌数据中...
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
{/* 卡牌预览 */}
|
||||
<Show when={!csvData.loading && store.cards.length > 0}>
|
||||
<CardPreview store={store}/>
|
||||
<Show when={!csvData.loading && store.cards.length > 0 && !store.error}>
|
||||
<CardPreview store={store} />
|
||||
</Show>
|
||||
|
||||
{/* 空状态 */}
|
||||
<Show when={!csvData.loading && store.cards.length === 0 && !store.error}>
|
||||
<div class="text-center text-gray-500 py-8">
|
||||
暂无卡牌数据
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createStore, produce } from 'solid-js/store';
|
||||
import { createStore } from 'solid-js/store';
|
||||
import { calculateDimensions } from '../utils/dimensions';
|
||||
import type { CardData, LayerConfig, Dimensions } from '../types';
|
||||
|
||||
export interface DeckState {
|
||||
|
|
@ -28,6 +29,9 @@ export interface DeckState {
|
|||
isSelecting: boolean;
|
||||
selectStart: { x: number; y: number } | null;
|
||||
selectEnd: { x: number; y: number } | null;
|
||||
|
||||
// 错误状态
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export interface DeckActions {
|
||||
|
|
@ -58,8 +62,9 @@ export interface DeckActions {
|
|||
setSelectEnd: (pos: { x: number; y: number } | null) => void;
|
||||
cancelSelection: () => void;
|
||||
|
||||
// 初始化
|
||||
initialize: (props: Record<string, any>, csvPath: string) => void;
|
||||
// 初始化和数据加载
|
||||
loadCards: (cards: CardData[]) => void;
|
||||
setError: (error: string | null) => void;
|
||||
|
||||
// 生成代码
|
||||
generateCode: () => string;
|
||||
|
|
@ -87,15 +92,39 @@ export function createDeckStore(): DeckStore {
|
|||
editingLayer: null,
|
||||
isSelecting: false,
|
||||
selectStart: null,
|
||||
selectEnd: null
|
||||
selectEnd: null,
|
||||
error: null
|
||||
});
|
||||
|
||||
const setSize = (size: string) => setState({ size });
|
||||
const setGrid = (grid: string) => setState({ grid });
|
||||
const setBleed = (bleed: string) => setState({ bleed });
|
||||
const setPadding = (padding: string) => setState({ padding });
|
||||
// 更新尺寸并重新计算 dimensions
|
||||
const updateDimensions = () => {
|
||||
const dims = calculateDimensions({
|
||||
size: state.size,
|
||||
grid: state.grid,
|
||||
bleed: state.bleed,
|
||||
padding: state.padding
|
||||
});
|
||||
setState({ dimensions: dims });
|
||||
};
|
||||
|
||||
const setCards = (cards: CardData[]) => setState({ cards });
|
||||
const setSize = (size: string) => {
|
||||
setState({ size });
|
||||
updateDimensions();
|
||||
};
|
||||
const setGrid = (grid: string) => {
|
||||
setState({ grid });
|
||||
updateDimensions();
|
||||
};
|
||||
const setBleed = (bleed: string) => {
|
||||
setState({ bleed });
|
||||
updateDimensions();
|
||||
};
|
||||
const setPadding = (padding: string) => {
|
||||
setState({ padding });
|
||||
updateDimensions();
|
||||
};
|
||||
|
||||
const setCards = (cards: CardData[]) => setState({ cards, activeTab: 0 });
|
||||
const setActiveTab = (index: number) => setState({ activeTab: index });
|
||||
const updateCardData = (index: number, key: string, value: string) => {
|
||||
setState('cards', index, key, value);
|
||||
|
|
@ -129,21 +158,23 @@ export function createDeckStore(): DeckStore {
|
|||
setState({ isSelecting: false, selectStart: null, selectEnd: null });
|
||||
};
|
||||
|
||||
const initialize = (props: Record<string, any>, csvPath: string) => {
|
||||
setState({
|
||||
size: props.size as string || '54x86',
|
||||
grid: props.grid as string || '5x8',
|
||||
bleed: props.bleed as string || '1',
|
||||
padding: props.padding as string || '2',
|
||||
fixed: props.fixed === true || props.fixed === 'true',
|
||||
src: csvPath
|
||||
});
|
||||
// 加载卡牌数据并初始化 dimensions 和 layerConfigs
|
||||
const loadCards = (cards: CardData[]) => {
|
||||
if (cards.length === 0) {
|
||||
setState({ error: 'CSV 文件为空或格式不正确' });
|
||||
return;
|
||||
}
|
||||
setState({ cards, activeTab: 0, error: null });
|
||||
updateDimensions();
|
||||
};
|
||||
|
||||
const setError = (error: string | null) => setState({ error });
|
||||
|
||||
const generateCode = () => {
|
||||
const layersStr = state.layerConfigs
|
||||
.map(l => `${l.prop}=${l.x1},${l.y1},${l.x2},${l.y2}`)
|
||||
.join('|');
|
||||
.filter(l => l.visible)
|
||||
.map(l => `${l.prop}:${l.x1},${l.y1}-${l.x2},${l.y2}`)
|
||||
.join(' ');
|
||||
return `:md-deck[${state.src}]{size="${state.size}" grid="${state.grid}" bleed="${state.bleed}" padding="${state.padding}" layers="${layersStr}"}`;
|
||||
};
|
||||
|
||||
|
|
@ -175,7 +206,8 @@ export function createDeckStore(): DeckStore {
|
|||
setSelectStart,
|
||||
setSelectEnd,
|
||||
cancelSelection,
|
||||
initialize,
|
||||
loadCards,
|
||||
setError,
|
||||
generateCode,
|
||||
copyCode
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { DeckStore } from '../stores/deckStore';
|
||||
import type { DeckStore } from './deckStore';
|
||||
|
||||
/**
|
||||
* 框选相关的操作(已整合到 deckStore)
|
||||
Loading…
Reference in New Issue